//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================

#pragma once

#include <VGUI.h>
#include <VGUI_MouseCode.h>
#include <VGUI_KeyCode.h>
#include <VGUI_Dar.h>
#include <VGUI_Cursor.h>

namespace vgui
{

class Panel;
class TickSignal;
class Scheme;
class TickSignal;
class SurfaceBase;

class VGUIAPI App
{
public:
	App();
	App(bool externalMain);

public:
	static App* getInstance();
	// TODO: the public and public bullshit are all messed up, need to organize
	// TODO: actually all of the access needs to be properly thought out while you are at it
public:
	virtual void start();
	virtual void stop();
	virtual void externalTick();
	virtual bool wasMousePressed(MouseCode code, Panel* panel);
	virtual bool wasMouseDoublePressed(MouseCode code, Panel* panel);
	virtual bool isMouseDown(MouseCode code, Panel* panel);
	virtual bool wasMouseReleased(MouseCode code, Panel* panel);
	virtual bool wasKeyPressed(KeyCode code, Panel* panel);
	virtual bool isKeyDown(KeyCode code, Panel* panel);
	virtual bool wasKeyTyped(KeyCode code, Panel* panel);
	virtual bool wasKeyReleased(KeyCode code, Panel* panel);
	virtual void addTickSignal(TickSignal* s);
	virtual void setCursorPos(int x, int y);
	virtual void getCursorPos(int& x, int& y);
	virtual void setMouseCapture(Panel* panel);
	virtual void setMouseArena(int x0, int y0, int x1, int y1, bool enabled);
	virtual void setMouseArena(Panel* panel);
	virtual void requestFocus(Panel* panel);
	virtual Panel* getFocus();
	virtual void repaintAll();
	virtual void setScheme(Scheme* scheme);
	virtual Scheme* getScheme();
	virtual void enableBuildMode();
	virtual long getTimeMillis();
	virtual char getKeyCodeChar(KeyCode code, bool shifted);
	virtual void getKeyCodeText(KeyCode code, char* buf, int buflen);
	virtual int getClipboardTextCount();
	virtual void setClipboardText(const char* text, int textLen);
	virtual int getClipboardText(int offset, char* buf, int bufLen);
	virtual void reset();
	virtual void internalSetMouseArena(int x0, int y0, int x1, int y1, bool enabled);
	virtual bool setRegistryString(const char* key, const char* value);
	virtual bool getRegistryString(const char* key, char* value, int valueLen);
	virtual bool setRegistryInteger(const char* key, int value);
	virtual bool getRegistryInteger(const char* key, int& value);
	virtual void setCursorOveride(Cursor* cursor);
	virtual Cursor* getCursorOveride();
	virtual void setMinimumTickMillisInterval(int interval);

public: // bullshit public stuff
	virtual void main(int argc, char* argv[]) = 0;
	virtual void run();
	virtual void internalCursorMoved(int x, int y, SurfaceBase* surfaceBase); // expects input in surface space
	virtual void internalMousePressed(MouseCode code, SurfaceBase* surfaceBase);
	virtual void internalMouseDoublePressed(MouseCode code, SurfaceBase* surfaceBase);
	virtual void internalMouseReleased(MouseCode code, SurfaceBase* surfaceBase);
	virtual void internalMouseWheeled(int delta, SurfaceBase* surfaceBase);
	virtual void internalKeyPressed(KeyCode code, SurfaceBase* surfaceBase);
	virtual void internalKeyTyped(KeyCode code, SurfaceBase* surfaceBase);
	virtual void internalKeyReleased(KeyCode code, SurfaceBase* surfaceBase);

private:
	virtual void init();
	virtual void updateMouseFocus(int x, int y, SurfaceBase* surfaceBase);
	virtual void setMouseFocus(Panel* newMouseFocus);

protected:
	virtual void surfaceBaseCreated(SurfaceBase* surfaceBase);
	virtual void surfaceBaseDeleted(SurfaceBase* surfaceBase);
	virtual void platTick();
	virtual void internalTick();

protected:
	static App* _instance;

protected:
	bool _running;
	bool _externalMain;
	Dar<SurfaceBase*> _surfaceBaseDar;
	Panel* _keyFocus;
	Panel* _oldMouseFocus;
	Panel* _mouseFocus;
	Panel* _mouseCapture;
	Panel* _wantedKeyFocus;
	bool _mousePressed[MOUSE_LAST];
	bool _mouseDoublePressed[MOUSE_LAST];
	bool _mouseDown[MOUSE_LAST];
	bool _mouseReleased[MOUSE_LAST];
	bool _keyPressed[KEY_LAST];
	bool _keyTyped[KEY_LAST];
	bool _keyDown[KEY_LAST];
	bool _keyReleased[KEY_LAST];
	Dar<TickSignal*> _tickSignalDar;
	Scheme* _scheme;
	bool _buildMode;
	bool _wantedBuildMode;
	Panel* _mouseArenaPanel;
	Cursor* _cursor[Cursor::dc_last];
	Cursor* _cursorOveride;

private:
	long _nextTickMillis;
	long _minimumTickMillisInterval;
	friend class SurfaceBase;
};
}
