#include <wx/wxprec.h>
#include <wx/datetime.h>
#include <wx/snglinst.h>
#include <wx/socket.h>
#include <wx/wfstream.h>
#ifdef LINUX
#include <wx/app.h>
#endif

#include "xml.h"

//////////////////////////////////////////////////////////
// Utilities
///////////////////////////////////////////////////////////

wxString Date2String(const wxDateTime& date);
wxDateTime String2Date(const wxString& str);

wxSocketBase& operator<<(wxSocketBase& outf, const wxChar* str);
wxSocketBase& operator<<(wxSocketBase& outf, wxString str);
wxSocketBase& operator<<(wxSocketBase& outf, size_t num);

//////////////////////////////////////////////////////////
// THashString
///////////////////////////////////////////////////////////

class THashString : public wxObject
{
public:
  wxString m_str;
	THashString(const wxChar* str) : m_str(str) { }
};

//////////////////////////////////////////////////////////
// THashTable
///////////////////////////////////////////////////////////

class THashTable : public wxObject
{
	wxHashTable m_Hash;

public:
  void Put(const wxString& key, const wxString& value);
	wxString Get(const wxChar* key) const;
  int GetInt(const wxChar* key) const { return atoi(Get(key)); }
  wxDateTime GetDate(const wxChar* key) const { return String2Date(Get(key)); }

	size_t GetCount() const { return m_Hash.GetCount(); } 
	void BeginFind() { m_Hash.BeginFind(); } 
  wxHashTable::Node* Next() { return m_Hash.Next(); } 

	THashTable(size_t size = 13);
};

//////////////////////////////////////////////////////////
// TTaskbarIcon
///////////////////////////////////////////////////////////

#ifdef WIN32
#include <wx/taskbar.h>

class TTaskBarIcon : public wxTaskBarIcon
{
protected:
  void OnTaskBarClick(wxTaskBarIconEvent& e);

public:
  void TTaskBarIcon::Init();

	DECLARE_EVENT_TABLE();
};

#endif

//////////////////////////////////////////////////////////
// TBaseServerApp
///////////////////////////////////////////////////////////

// Define a new application type
class TBaseServerApp : public wxApp
{
private:
  wxSocketServer* m_server;
	wxFileOutputStream* m_log;
  wxString m_strPath, m_strTempDir, m_strIni;
	bool m_bRunning;
	int m_nTmpCounter;
	wxArrayPtrVoid m_Sockets;

#ifdef WIN32
  TTaskBarIcon* m_Tray;
#endif
  
protected:
  wxSingleInstanceChecker* m_SingleInstance;

  virtual void ProcessCommand(wxString cmd, wxSocketBase& outs);
	virtual bool CanProcessCommand(wxString& cmd, wxSocketBase& outs);
	
  virtual const wxString& GetServerPath() const { return m_strPath; }
	virtual wxString GetDocumentRoot() const; 

	virtual TXmlItem& AddLogo(TXmlItem& td) const;

	// Used by SendFile
	void SendContent(wxFileInputStream& inf, wxSocketBase& sock);
  void SendNotModifiedFile(wxSocketBase& sock);

  virtual void SoapProcessMethod(const TXmlItem& xmlMethod, TXmlItem& xmlAnswer);
  virtual void ProcessSoapCommand(wxString cmd, wxSocketBase& sock);
  virtual void ProcessFormCommand(wxString cmd, wxSocketBase& outs);
  virtual void ProcessHttpGet(wxString cmd, wxSocketBase& outs);

public:
  // Utilities
	virtual const wxChar* GetAppName() const = 0;
	virtual const wxString& GetConfigName() const;
	virtual int GetDefaultPort() const;       // Retrieves Port usig GetConfigInt
	virtual void SetConfigString(const wxChar* key, const wxChar* val, const wxChar* app = NULL) const;
	
	void SetConfigInt(const wxChar* key, int val, const wxChar* app = NULL) const;
	virtual wxString GetConfigString(const wxChar* key, const wxChar* def = "", const wxChar* app = NULL) const;
	int GetConfigInt(const wxChar* key, int def = 0, const wxChar* app = NULL) const;        // Uses GetConfigString
	bool GetConfigBool(const wxChar* key, bool def = false, const wxChar* app = NULL) const; // Uses GetConfigString
	virtual wxString GetLogFileName() const;
	
	wxString GetTempFilename(const wxChar * ext = "htm");
	TXmlItem& CreatePageBody(TXmlItem& html, wxString header = "") const;
  TXmlItem& AddLinkButton(TXmlItem& body, const wxChar* strCaption, const wxChar* strHref) const;

  void SendFile(wxString strFilename, wxSocketBase& sock);
  void MessageBox(const wxChar* caption, const wxChar* msg, wxSocketBase& sock);

	wxString UnformatString(const wxString& strFormString) const;
  size_t ParseArguments(wxString args, THashTable& hashArgs) const;

	virtual void WriteLog(const wxChar* str) const; // Writes on log file if present                   
	virtual bool Ok() const { return m_server->Ok(); }
	virtual bool Initialization() { return true; }
	virtual bool Deinitialization() { return true; }

  // Initialization (Do NOT use nor reimplement!)
  virtual bool OnInit();
  virtual int OnExit();
  void OnServerEvent(wxSocketEvent& event);
  void OnSocketEvent(wxSocketEvent& event);
  void OnIdle(wxIdleEvent& event);
	DECLARE_EVENT_TABLE();
};

TBaseServerApp& GetServerApp();