#pragma once

#include "Workspace.h"
#include "threadskeleton.h"
#include "logwriter.h"
#include "mimetypemgr.h"
#include "bandwidthmgr.h"
#include "ListenerManager.h"
#include "IntervalTimer.h"
#include "SSLContext.h"
#include "ContextManager.h"
#include "AuthenticateManager.h"



/*!
	class CSettingSwap

	サーバ設定の置き換え
*/
class CSettingSwap : public IWorkspaceAutoSwap
{
public:
	CSettingSwap(CWorkspaceAccess serverInfo) {m_serverInfo = serverInfo;};
	CString SwapString(CString key,CString data);
	void Delete() { delete this; };

	CWorkspaceAccess	m_serverInfo;	
};


/*!
	class CServer

	サーバ処理を行います
*/
class CServer : public CThreadSkeleton
{
public:
	CServer(void);
	virtual ~CServer(void);

	/////////////////////////////////////////////////////////////////////////////
	//	サーバツール
	/////////////////////////////////////////////////////////////////////////////
	//!	MIMEタイプマネージャの取得
	CMimeTypeMgr GetCMimeTypeMgr() { SCOPE_LOCK(); return m_mimeTypes; };

	//!	帯域幅マネージャの取得
	CBandWidthMgr *GetCBandWidthMgr() { return &m_bandWidthMgr; };

	//!	コンテキストマネージャ取得
	CContextManager *GetContextManager() { return &m_contextMgr; };

	//!	認証マネージャ取得
	CAuthenticateManager *GetAuthManager() { return &m_authMgr; };

	//!	転送量を設定
	void AddTrans(__int64 send,__int64 recv) { m_bandWidthMgr.AddTrans(send,recv); };

	//!	接続数を取得
	int GetConnectCount();

	//!	オーバーロード常態か取得
	int ServerIsOverload();

	//!	SSLコンテキスト取得
	SSL_CTX *GetCTX() { return m_sslContext.GetCTX(); };

protected:
	/////////////////////////////////////////////////////////////////////////////
	//	サーバ起動系
	/////////////////////////////////////////////////////////////////////////////
	//!	サーバ情報の設定
	void InitServerInfo(void);

	//!	待ち受け開始
	int StartListen(void);

	//!	全ての接続の停止
	void KillAllConnection();

	//!	SSL初期化
	void InitSSL();

	/////////////////////////////////////////////////////////////////////////////
	//	サーバ処理系
	/////////////////////////////////////////////////////////////////////////////
	//!	スレッド本体
	void ThreadMain();

	//!	次の接続を待つ
	void WaitNextConnection(int timeout);

	//!	次のアクセスを取得
	int GetNextAccess(CAcceptedSocket &nextAccess, int waitTime);

	//!	切断した接続を破棄
	void ClearCompletedConnections();

	//!	サーバ負荷調整
	void CheckServerLoad();

	//!	サーバ情報を更新
	void UpdateServerInfo();

	//!	サーバステータスを設定
	void SetServerStatus(CString status, CTimeSpan viewTime = CTimeSpan(1,0,0,0));

protected:
	//////////////////////////////////////////////////////////////////////////////////////
	//	メンバ変数
	//////////////////////////////////////////////////////////////////////////////////////
	//!	最大接続数
	int					m_maxConnect;

	//!	接続
	CPtrArray			m_connections;

	//!	コンテキストマネージャ
	CContextManager		m_contextMgr;

	//!	MimeTypeのキャッシュ
	CMimeTypeMgr		m_mimeTypes;

	//!	帯域制限
	CBandWidthMgr		m_bandWidthMgr;

	//!	ダイジェスト認証マネージャ
	CAuthenticateManager	m_authMgr;

	//!	リスナ
	CListenerManager	m_listener;

	//!	SSLコンテキスト
	CSSLContext			m_sslContext;

	//!	高負荷フラグ
	CInterlockCounter	m_overloadFlag;

	//!	高負荷と判断する閾値
	int					m_overloadThreshold;

	//!	高負荷状態維持タイマ
	CIntervalTimer		m_overloadKeepTimer;

	//!	サーバステータスを消す時刻
	CTime				m_statusHideTime;

public:
	CWorkspace			m_settingRoot;			//!<	設定ルート
	CWorkspace			m_infoRoot;				//!<	サーバ情報ルート
	CWorkspaceAccess	m_serverInfo;			//!<	サーバ情報環境領域

	//!	設定
	CWorkspaceAccess	m_setting;


	CLogWriter			m_log;					//!<	ログライター
};

