//------------------------------------------------------------------------------
// Lamp : Open source game middleware
// Copyright (C) 2004  Junpei Ohtani ( Email : junpee@users.sourceforge.jp )
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//------------------------------------------------------------------------------

/** @file
 * Lampグラフィックスヘッダ
 * @author Junpee
 */

#ifndef LAMP_GRAPHICS_H_
#define LAMP_GRAPHICS_H_

#include <Core/Container/ArrayList.h>
#include <Core/Container/HashMap.h>
#include <Graphics/Scene/Scene.h>

namespace Lamp{

class GraphicsDeviceEnumeration;
class GraphicsDeviceSelector;
class GraphicsDeviceSettings;
class GraphicsDevice;
class GraphicsDeviceCapacity;
class RenderingDevice;
class ShaderManager;
class GraphicsDeviceObjectHolder;
class Scene;

//------------------------------------------------------------------------------
/**
 * Lampグラフィックス
 */
class LampGraphics{
friend class LampCore;
friend class GraphicsDevice;
public:
	/**
	 * 初期化
	 */
	static void initialize();

	/**
	 * デバイスの初期化
	 *
	 * 列挙の条件設定はデバイス初期化前に行う必要がある。
	 * デバイスセレクタの設定はデバイス初期化前に行う必要がある。
	 * @param windowHandle ウィンドウハンドル
	 * @param startFullscreen フルスクリーンを優先して初期化するならtrue
	 * @return デバイスの初期化に成功すればtrue
	 */
	static bool initializeDevice(HWND windowHandle, bool startFullscreen);

	/**
	 * 後始末
	 */
	static void finalize();

	//--------------------------------------------------------------------------
	/**
	 * グラフィックスデバイスセレクタの設定
	 *
	 * 設定したセレクタはLampGraphicsによりdeleteされます
	 * @param selector グラフィックスデバイスセレクタ
	 */
	static void setDeviceSelector(GraphicsDeviceSelector* selector);

	/**
	 * グラフィックスデバイスセレクタの取得
	 * @return グラフィックスデバイスセレクタ
	 */
	static GraphicsDeviceSelector* getDeviceSelector(){ return selector_; }

	//--------------------------------------------------------------------------
	/**
	 * ウィンドウハンドルの取得
	 * @return ウィンドウハンドル
	 */
	static HWND getWindowHandle(){ return windowHandle_; }

	/**
	 * Direct3Dの取得
	 * @return Direct3D
	 */
	static Direct3D* getDirect3D(){ return direct3D_; }

	/**
	 * Direct3Dデバイスの取得
	 * @return Direct3Dデバイス
	 */
	static Direct3DDevice* getDirect3DDevice(){ return direct3DDevice_; }

	//--------------------------------------------------------------------------
	// デバイスオブジェクトホルダ
	//--------------------------------------------------------------------------
	/**
	 * デバイスオブジェクトホルダの追加
	 * @param objectHolder 追加するデバイスオブジェクトホルダ
	 */
	static void addDeviceObjectHolder(GraphicsDeviceObjectHolder* objectHolder){
		deviceObjectHolders_.add(objectHolder);
	}

	/**
	 * デバイスオブジェクトホルダの削除
	 * @param objectHolder 削除するデバイスオブジェクトホルダ
	 */
	static void removeDeviceObjectHolder(
		GraphicsDeviceObjectHolder* objectHolder){
		deviceObjectHolders_.removeByValue(objectHolder);
	}

	/**
	 * デバイスオブジェクトホルダ数の取得
	 * @return デバイスオブジェクトホルダ数
	 */
	static int getDeviceObjectHolderCount(){
		return deviceObjectHolders_.getCount();
	}

	/**
	 * デバイスオブジェクトホルダの取得
	 * @param index デバイスオブジェクトホルダのインデクス
	 * @return デバイスオブジェクトホルダ
	 */
	static GraphicsDeviceObjectHolder* getDeviceObjectHolder(int index){
		return deviceObjectHolders_.get(index);
	}

	//--------------------------------------------------------------------------
	// シーン関係、初期化無しでアクセス可能
	//--------------------------------------------------------------------------
	/**
	 * シーンの作成
	 * @param name 名前
	 * @return 作成されたシーン
	 */
	static Scene* createScene(const String& name);

	/**
	 * シーンの破棄
	 * @param scene 破棄するシーン
	 */
	static void destroyScene(Scene* scene);

	/**
	 * シーン数の取得
	 * @return シーン数
	 */
	static int getSceneCount(){ return sceneArray_.getCount(); }

	/**
	 * シーンの取得
	 * @param index シーンのインデクス
	 * @return シーン
	 */
	static Scene* getScene(int index){ return sceneArray_.get(index); }

	/**
	 * シーンの検索
	 * @param name 検索するシーン名
	 * @return シーン
	 */
	static Scene* search(String name){ return sceneDatabase_.get(name); }

	//--------------------------------------------------------------------------
protected:
	/**
	 * ウィンドウプロシージャ
	 * @param windowHandle ウィンドウハンドル
	 * @param message メッセージ
	 * @param wParam wメッセージパラメータ
	 * @param lParam lメッセージパラメータ
	 * @return メッセージを処理し、それ以上の処理が必要無いならば0以外を返す。
	 */
	static LRESULT windowProcedure(
		HWND windowHandle, u_int message, WPARAM wParam, LPARAM lParam);

	//--------------------------------------------------------------------------
	/**
	 * デバイスがリセットされた
	 */
	static void deviceReset();

	/**
	 * デバイスオブジェクトの初期化
	 * @return 成功したらtrueを返す
	 */
	static bool initializeDeviceObjects();

	/**
	 * デバイスオブジェクトの削除
	 */
	static void deleteDeviceObjects();

	/**
	 * デバイスオブジェクトのリストア
	 * @return 成功したらtrueを返す
	 */
	static bool restoreDeviceObjects();

	/**
	 * デバイスオブジェクトの無効化
	 */
	static void invalidateDeviceObjects();

	//--------------------------------------------------------------------------
private:
	// コンストラクタの隠蔽
	LampGraphics();

	// ウィンドウハンドル
	static HWND windowHandle_;
	// グラフィックスデバイスの列挙
	static GraphicsDeviceEnumeration* enumeration_;
	// グラフィックスデバイスセレクタ
	static GraphicsDeviceSelector* selector_;
	// グラフィックスデバイス設定
	static GraphicsDeviceSettings* settings_;
	// グラフィックスデバイス
	static GraphicsDevice* device_;
	// Direct3Dデバイス
	static Direct3DDevice* direct3DDevice_;
	// グラフィックスデバイス能力
	static GraphicsDeviceCapacity* deviceCapacity_;
	// レンダリングデバイス
	static RenderingDevice* renderingDevice_;
	// シェーダマネージャ
	static ShaderManager* shaderManager_;
	// Direct3D
	static Direct3D* direct3D_;
	// デバイスオブジェクトホルダ
	static ArrayList<GraphicsDeviceObjectHolder*> deviceObjectHolders_;

	// シーン配列
	static ArrayList<Scene*> sceneArray_;
	// シーンデータベース
	static HashMap<String, Scene*> sceneDatabase_;
	// シーンキャパシティ
	static const int scenesCapacity_ = 16;

	// 初期化フラグ
	static bool isInitialized_;
	// デバイス初期化フラグ
	static bool deviceInitialized_;
};

//------------------------------------------------------------------------------
} // End of namespace Lamp
#endif // End of LAMP_GRAPHICS_H_
//------------------------------------------------------------------------------

