/*
 * OpenClonk, http://www.openclonk.org
 *
 * Copyright (c) 2003-2007  Sven Eberhardt
 * Copyright (c) 2005  Peter Wortmann
 * Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de
 *
 * Portions might be copyrighted by other authors who have contributed
 * to OpenClonk.
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 * See isc_license.txt for full license and disclaimer.
 *
 * "Clonk" is a registered trademark of Matthes Bender.
 * See clonk_trademark_license.txt for full license.
 */
// the ingame-lobby

// Tab: NickCompletion (2do TODO) - and can't do this here, because tab is used to cycle controls!
//if (dwKey == VK_TAB) { /*CompleteNick();*/ return true; }

#ifndef INC_C4GameLobby
#define INC_C4GameLobby

#include "C4Gui.h"
#include "C4Client.h"
#include "C4PlayerInfo.h"

namespace C4GameLobby
{
	class MainDlg;

	// countdown time from which the elevator sound starts and team selection becomes unavailable
	const int32_t AlmostStartCountdownTime = 10; // seconds

	extern bool UserAbort;

	// * PID_LobbyCountdown
	// initiates or aborts countdown
	class C4PacketCountdown : public C4PacketBase
	{
	private:
		int32_t iCountdown; // countdown timer, or zero for abort
	public:
		enum { Abort = -1 };

		C4PacketCountdown(int32_t iaCountdown) : iCountdown(iaCountdown) { } // ctor
		C4PacketCountdown() : iCountdown(Abort) { } // std ctor

		bool IsAbort() const { return iCountdown == Abort; }
		int32_t GetCountdown() const { return iCountdown; }
		StdStrBuf GetCountdownMsg(bool fInitialMsg=false) const;

		virtual void CompileFunc(StdCompiler *pComp);
	};

	// scneario info tab: displays scenario description
	class ScenDesc : public C4GUI::Window, private C4ApplicationSec1Timer
	{
	private:
		C4GUI::Label *pTitle;            // scenario title or warning label if unloaded
		C4GUI::TextWindow *pDescBox;     // scenario description box
		bool fDescFinished;              // if set, scenario resource has been loaded

		void Update();

	public:
		ScenDesc(const C4Rect &rcBounds, bool fActive); // ctor
		~ScenDesc() { Deactivate(); }

		void OnSec1Timer() { Update(); }
		// activate/deactivate periodic updates
		void Activate();
		void Deactivate();
	};

	class MainDlg : public C4GUI::FullscreenDialog, private C4ApplicationSec1Timer
	{
	private:
		time_t tLastPingUpdate; // time when pings were updated last time
		enum CountdownState { CDS_None=0, CDS_LongCountdown=1, CDS_Countdown=2, CDS_Start=3 } eCountdownState; // nonzero when a packet was received that the game is about to start (starts elevator sound, etc.)
		int32_t iBackBufferIndex;   // chat message history index
		C4KeyBinding *pKeyHistoryUp, *pKeyHistoryDown; // keys used to scroll through chat history

		enum { SheetIdx_PlayerList = 0, SheetIdx_Res = 1, SheetIdx_Options = 2, SheetIdx_Scenario = 3 };
		C4PlayerInfoListBox *pPlayerList;
		C4Network2ResDlg *pResList;
		C4GameOptionButtons *pGameOptionButtons;
		C4GameOptionsList *pOptionsList;
		ScenDesc *pScenarioInfo;
		C4GUI::TextWindow *pChatBox;
		C4GUI::Label *pRightTabLbl;
		C4GUI::Tabular *pRightTab;
		C4GUI::Edit *pEdt; // chat input
		C4GUI::CallbackButton<MainDlg> *btnRun; // host only
		C4GUI::CallbackButton<MainDlg, C4GUI::IconButton> *btnPlayers, *btnResources, *btnTeams, *btnOptions, *btnScenario, *btnChat; // right list sheet selection

	protected:
		void OnRunBtn(C4GUI::Control *btn); // callback: run button pressed
		void OnTestBtn(C4GUI::Control *btn); // callback: test button pressed
		void OnExitBtn(C4GUI::Control *btn); // callback: exit button pressed
		bool KeyHistoryUpDown(bool fUp); // key callback
		C4GUI::Edit::InputResult OnChatInput(C4GUI::Edit *edt, bool fPasting, bool fPastingMore); // callback: chat input performed

		void OnClosed(bool fOK); // callback when dlg is closed
		void OnSec1Timer();              // timer proc; update pings

		C4GUI::ContextMenu *OnRightTabContext(C4GUI::Element *pLabel, int32_t iX, int32_t iY); // open context menu
		void OnCtxTabPlayers(C4GUI::Element *pListItem) { OnTabPlayers(NULL); }
		void OnTabPlayers(C4GUI::Control *btn);
		void OnCtxTabTeams(C4GUI::Element *pListItem) { OnTabTeams(NULL); }
		void OnTabTeams(C4GUI::Control *btn);
		void OnCtxTabRes(C4GUI::Element *pListItem) { OnTabRes(NULL); }
		void OnTabRes(C4GUI::Control *btn);
		void OnCtxTabOptions(C4GUI::Element *pListItem) { OnTabOptions(NULL); }
		void OnTabOptions(C4GUI::Control *btn);
		void OnCtxTabScenario(C4GUI::Element *pListItem) { OnTabScenario(NULL); }
		void OnTabScenario(C4GUI::Control *btn);
		void UpdateRightTab(); // update label and tooltips for sheet change
		void OnBtnChat(C4GUI::Control *btn);

		virtual class C4GUI::Control *GetDefaultControl() { return pEdt; } // def focus chat input

	private:
		void SetCountdownState(CountdownState eToState, int32_t iTimer);
		int32_t ValidatedCountdownTime(int32_t iTimeout); // correct invalid timeout settings

		void UpdatePlayerList();

	public:
		MainDlg(bool fHost); // ctor
		~MainDlg(); // dtor

		// callback by network system
		void OnClientJoin(C4Client *pNewClient); // called when a new client joined (connection not necessarily ready)
		void OnClientConnect(C4Client *pClient, C4Network2IOConnection *pConn); // called when new clinet connection is established (notice of lobby status)
		void OnClientPart(C4Client *pPartClient); // called when a client disconnects
		bool OnMessage(C4Client *pOfClient, const char *szMessage); // display message in chat window
		void OnClientSound(C4Client *pOfClient);                    // show that someone played a sound
		void OnLog(const char *szLogMsg, DWORD dwClr=C4GUI_LogFontClr); // log callback
		void OnError(const char *szErrMsg); // error sound + log in red
		void OnPlayersChange() { UpdatePlayerList(); }
		void OnClientAddPlayer(const char *szFilename, int32_t idClient);
		// packet callbacks from C4Network2
		void HandlePacket(char cStatus, const C4PacketBase *pBasePkt, C4Network2Client *pClient);
		void OnCountdownPacket(const C4PacketCountdown &Pkt); // called when a countdown packet is received: Update countdown state

		bool IsCountdown();
		void Start(int32_t iCountdownTime); // host only: Do game start with specified countdown time (forwards to network system)
		void UpdatePassword();
		void ClearLog();
	};

	// helper
	void LobbyError(const char *szErrorMsg);

	// lobby countdown: Moves game from lobby to go state. Only created by host.
	class Countdown : private C4ApplicationSec1Timer
	{
	private:
		int32_t iStartTimer;        // countdown timer for round start; 0 for not started, -1 for start overdue

	public:
		void OnSec1Timer();              // timer proc; count down; send important countdown packets

	public:
		Countdown(int32_t iStartTimer); // ctor: Init; sends initial countdown packet
		~Countdown();

		void Abort();
	};

}

#endif
