#include <mglaugust2.h>
#include <roast/roast.hpp>
#include <vector>
#include <string>

#undef GetClassName		//	すごい強引に誤魔化す・・・（暫定

#define PARENT_STR		".."
#define ITEM_INTERVAL	(17)
#define TITLE			"Neptune Explorer - v0.000000001(β1)"

using namespace std;

//////////////////////////////////////////////////////

//	ファイル・ディレクトリの1項目（CAugustText2を継承）
class CFileItem : public CAugustText2
{
public:
	static const char* CLASS_NAME;
protected:
	roast::CFile m_file;

	CAugust2dSquare2 m_bg;		//	マウスカーソル合わせた時に白くなるアレ
	CAugustImage2 m_imgIcon;	//	アイコン

_AGH_EVENT_ACCESS_MODIFIER:
	virtual void OnRegist()
	{
		CAugustText2::OnRegist();

		RegistControl(&m_bg);
		RegistControl(&m_imgIcon);
	}

	//	白四角のフェードアウト処理
	virtual bool OnFrame(){
		int al = m_bg.GetAlpha() - 8;
		if ( al < 0 )
			al = 0;
		m_bg.SetAlpha(al);

		return true;
	}

public:
	CFileItem(){
		SetClassName(CLASS_NAME);
	}
	
	void SetFile(roast::CFile &file)
	{
		m_file = file;

		SetText(m_file.GetFullPath());

		//	アイコン設定
		if ( m_file.IsFile() )
			m_imgIcon.Load("file.bmp");
		else
			m_imgIcon.Load("folder.bmp");
		m_imgIcon.SetPos(-16,-2);

		//	その他場所とか色とか
		m_bg.SetRect(0,0,400,15);
		m_bg.SetColor(0);

		this->SetRect(0,0,400,15);
		this->SetColor(0x80000000);
	}

	void OverCursor()
	{
		m_bg.SetColor(AGHCOLOR_XRGB(200,200,200));
	}
};
const char* CFileItem::CLASS_NAME = "sf/jp/neptune/CFileItem";


//////////////////////////////////////////////////////

//	メインフレームクラス
class CMyFrame : public CAugustWindowFrame2
{
private:
	CAugustMouseInput m_mouse;		//	マウス入力管理
	CAugustText2 m_txtTitle;		//	ファイルパス行
	CAugustText2 m_frameRateTitle;	//	フレームレート表示
	agh::CControlArray<CFileItem> m_fileAry;	//	ファイル群

	//	ファイルの追加
	void AddFile(roast::CFile &file)
	{
		CFileItem& rItem = m_fileAry.Add();

		rItem.SetFile(file);
		rItem.SetPos(22, m_fileAry.size()*ITEM_INTERVAL);
	}

public:

	//	初期化時に呼ばれる
	bool OnGraphicInitEnded()
	{
		//	コントロールクラスの登録
		RegistControl(&m_txtTitle);
		RegistControl(&m_frameRateTitle);
		RegistControl(&m_mouse);
		RegistControl(&m_fileAry);

		///////////////////////////////////////////

		//DirSel("C:\\");
		DriveList();

		//	マウスクリックハンドラの登録
		m_mouse.RegistHandler(
			CAugustMouseInput::EVTTYPE_ON_DOWN,
			CAugustMouseInput::LBUTTON,
			(CAugustMouseInput::CALLBACK_TYPE_MI)&CMyFrame::OnMouseLDown,
			this);

		//	マウス移動ハンドラの登録
		m_mouse.RegistHandler(
			CAugustMouseInput::EVTTYPE_ON_MOVE,
			0,
			(CAugustMouseInput::CALLBACK_TYPE_MI)&CMyFrame::OnMouseMove,
			this);

		//	マウスホイールハンドラの登録
		m_mouse.RegistHandler(
			CAugustMouseInput::EVTTYPE_ON_MOVE,
			CAugustMouseInput::CBUTTON,
			(CAugustMouseInput::CALLBACK_TYPE_MI)&CMyFrame::OnMouseWheel,
			this);

		//	背景色
		this->SetColor(AGHCOLOR_XRGB(150,100,100));

		//	FPS表示の場所設定
		m_frameRateTitle.SetPos(730,600-20);

		return true;
	}

	//////////////////////////////////////////////////////

	//	クリック時に呼ばれる
	bool OnMouseLDown(int x, int y)
	{
		//	クリックした箇所のコントロールを取得
		agh::CVisualControlBase *pCtrl = m_fileAry.HitTestRecursive(agh::CPoint(x,y));
		
		//	NULL以外＝クリックした箇所にコントロール有り, NULL＝コントロールなし
		if ( pCtrl != NULL )
		{
			//	そのクラスがCFileItemであるかを判定
			if ( strcmp( pCtrl->GetClassName(), CFileItem::CLASS_NAME ) == 0 )
			{
				CFileItem* pFileItem = (CFileItem*)pCtrl;

				std::string strText = pFileItem->GetText();	//	一旦別変数にコピーしておかないと、Clear()でコントロールが消滅した時にNGになる・・・
				
				//	「..」の場合
				if ( strText.compare(PARENT_STR) == 0 ){
					std::string parent = roast::CFile(m_txtTitle.GetText()).GetParent().GetFilePath();
					
					if ( *(parent.c_str()) == '\0' )
						DriveList();
					else
						DirSel( parent.c_str() );
				}
				
				//	「..」以外
				else {
					if ( roast::CFile(strText).IsFile() ){
						//	ファイルの実行（超暫定・・・）
						system(strText.c_str());
					}
					else {
						//	ディレクトリ選択
						DirSel(strText.c_str());
					}
				}
			}
		}
		return true;
	}

	//	マウス移動時に呼ばれる
	bool OnMouseMove(int x, int y)
	{
		//	現在のマウスカーソルのコントロールを取得
		agh::CVisualControlBase *pCtrl = m_fileAry.HitTestRecursive(m_mouse.GetCursorPos());
		
		//	NULL以外＝カーソル位置にコントロール有り, NULL＝コントロールなし
		if ( pCtrl != NULL )
		{
			//	そのクラスがCFileItemであるかを判定
			if ( strcmp( pCtrl->GetClassName(), CFileItem::CLASS_NAME ) == 0 )
			{
				CFileItem* pFileItem = (CFileItem*)pCtrl;

				pFileItem->OverCursor();
			}
		}
		return true;
	}

	//	マウスホイール時に呼ばれる
	bool OnMouseWheel(int x, int y)
	{
		//	上に行きすぎないようにする
		if ( x > 0 ){
			if ( m_fileAry.GetPos().y < 0 )
				m_fileAry.Move(0, ITEM_INTERVAL*3 );
		}
		else{
			m_fileAry.Move(0, -ITEM_INTERVAL*3 );
		}
		return true;
	}

	//	ウインドウ生成前に呼ばれる
	void OnCreateWindow(agh::CREATE_WINDOW_INFO *pWindowInfo){
		pWindowInfo->nWinWidthSize = 800;
		pWindowInfo->nWinHeightSize = 600;
		pWindowInfo->strWindowTitle = TITLE;
	}

	////////////////////////////////////////////////

	//	ドライブ一覧
	void DriveList()
	{
		m_fileAry.SetPos(0,0);
		m_fileAry.Clear();

		this->SetWindowTitle(TITLE);
		m_txtTitle.SetText("");

		std::vector<roast::CFile> fileList;
		roast::CFile::GetDriveList( fileList );

		for(size_t i=0; i<fileList.size(); i++)
		{
			AddFile(fileList[i]);
		}
	}

	//	ディレクトリを選択
	void DirSel(const char* szDir)
	{
		m_fileAry.SetPos(0,0);
		m_fileAry.Clear();

		this->SetWindowTitle(szDir);
		m_txtTitle.SetText(szDir);
		
		std::vector<roast::CFile> fileList;
		roast::CFile(szDir).GetChildList( fileList );

		//	「..」を追加
		AddFile(roast::CFile(PARENT_STR));

		for(size_t i=0; i<fileList.size(); i++)
		{
			AddFile(fileList[i]);
		}
	}

	virtual bool OnFrame(){
		//	フレームレート表示
		char work[256];
		sprintf(work, "%f", m_fps.GetAveFps());
		m_frameRateTitle.SetText(work);

		return true;
	}
};

//	WinMain
int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow )
{
	CMyFrame frame;
	frame.Start();
	return 0;
}
