//------------------------------------------------------------------------------
// 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
 * 描画リクエストヘッダ
 * @author Junpee
 */

#ifndef DRAW_REQUEST_H_
#define DRAW_REQUEST_H_

#include <Core/Container/ArrayList.h>

namespace Lamp{

class Fog;
class Camera;
class SceneNode;
class Model;
class Mesh;
class MeshData;
class Material;
class LocalLight;
class AmbientLight;
class DirectionalLight;

//------------------------------------------------------------------------------
/**
 * 描画リクエスト
 */
class DrawRequest{
friend class Renderer;
public:
	//--------------------------------------------------------------------------
	// メッシュ情報
	//--------------------------------------------------------------------------
	/**
	 * メッシュの取得
	 * @return メッシュ
	 */
	virtual Mesh* getMesh() const{ return mesh_; }

	/**
	 * メッシュに変更があったか
	 * @return メッシュに変更があればtrue
	 */
	virtual bool isMeshChanged() const{ return (mesh_ != preMesh_); }

	/**
	 * シーンノードの取得
	 * @return シーンノード
	 */
	virtual SceneNode* getSceneNode() const{ return sceneNode_; }

	/**
	 * シーンノードに変更があったか
	 * @return シーンノードに変更があればtrue
	 */
	virtual bool isSceneNodeChanged() const{
		return (sceneNode_ != preSceneNode_);
	}

	/**
	 * モデルの取得
	 * @return モデル
	 */
	virtual Model* getModel() const{ return model_; }

	/**
	 * モデルに変更があったか
	 * @return モデルに変更があればtrue
	 */
	virtual bool isModelChanged() const{ return (model_ != preModel_); }

	/**
	 * メッシュデータの取得
	 * @return メッシュデータ
	 */
	virtual MeshData* getMeshData() const{ return meshData_; }

	/**
	 * メッシュデータに変更があったか
	 * @return メッシュデータに変更があればtrue
	 */
	virtual bool isMeshDataChanged() const{
		return (meshData_ != preMeshData_);
	}

	/**
	 * マテリアルの取得
	 * @return マテリアル
	 */
	virtual Material* getMaterial() const{ return material_; }

	/**
	 * 前のマテリアルの取得
	 * @return 前のマテリアル
	 */
	virtual Material* getPreMaterial() const{ return preMaterial_; }

	/**
	 * マテリアルに変更があったか
	 * @return マテリアルに変更があればtrue
	 */
	virtual bool isMaterialChanged() const{
		return (material_ != preMaterial_);
	}

	/**
	 * 正規化を必要とするか
	 * @return 正規化を必要とするならtrue
	 */
	virtual bool requireNormalize() const;

	/**
	 * パイプラインモードに変更があったか
	 * @return パイプラインモードに変更があればtrue
	 */
	virtual bool isPipelineModeChanged() const;

	//--------------------------------------------------------------------------
	// フォグ
	//--------------------------------------------------------------------------
	/**
	 * フォグの取得
	 * @return フォグ
	 */
	virtual Fog* getFog() const{ return fog_; }

	//--------------------------------------------------------------------------
	// カメラ
	//--------------------------------------------------------------------------
	/**
	 * カメラの取得
	 * @return カメラ
	 */
	virtual Camera* getCamera() const{ return camera_; }

	//--------------------------------------------------------------------------
	// アンビエントライト
	//--------------------------------------------------------------------------
	/**
	 * アンビエントライト数の取得
	 * @return アンビエントライト数
	 */
	virtual int getAmbientLightCount() const{
		return ambientLights_.getCount();
	}

	/**
	 * アンビエントライトの取得
	 */
	virtual AmbientLight* getAmbientLight(int index) const{
		return ambientLights_.get(index);
	}

	/**
	 * アンビエント色の取得
	 * @return アンビエント色
	 */
	Color3f getAmbientColor() const;

	//--------------------------------------------------------------------------
	// ディレクショナルライト
	//--------------------------------------------------------------------------
	/**
	 * ディレクショナルライト数の取得
	 * @return ディレクショナルライト数
	 */
	virtual int getDirectionalLightCount() const{
		return directionalLights_.getCount();
	}

	/**
	 * ディレクショナルライトの取得
	 */
	virtual DirectionalLight* getDirectionalLight(int index) const{
		return directionalLights_.get(index);
	}

	//--------------------------------------------------------------------------
	// ローカルライト
	//--------------------------------------------------------------------------
	/**
	 * ローカルライトの追加
	 * @param localLight 追加するライト
	 */
	virtual void addLocalLight(LocalLight* localLight);

	/**
	 * ローカルライトのクリア
	 */
	virtual void clearLocalLights(){ localLights_.clear(); }

	/**
	 * ローカルライト数の取得
	 * @return ローカルライト数
	 */
	virtual int getLocalLightCount() const{ return localLights_.getCount(); }

	/**
	 * ローカルライトの取得
	 */
	virtual LocalLight* getLocalLight(int index) const{
		return localLights_.get(index);
	}

	/**
	 * ローカルライトのソート
	 */
	virtual void sortLocalLights(){
		localLights_.sort(sortLocalLightsCallback);
	}

	//--------------------------------------------------------------------------
	/**
	 * ローカルライトのソート用コールバック
	 * @param left 左辺値
	 * @param right 右辺値
	 * @return 左辺値が右辺値より大きいときは1以上
	 */
	static int sortLocalLightsCallback(
		LocalLight* const* left, LocalLight* const* right);

protected:
	//--------------------------------------------------------------------------
	// レンダラから使用されるインターフェース
	//--------------------------------------------------------------------------
	/**
	 * コンストラクタ
	 */
	DrawRequest();

	/**
	 * デストラクタ
	 */
	virtual ~DrawRequest();

	//--------------------------------------------------------------------------
	/**
	 * クリア
	 */
	virtual void clear();

	//--------------------------------------------------------------------------
	/**
	 * ブレンドが有効になった
	 * @return ブレンドが有効になったのならtrue
	 */
	virtual bool isBlendEnabled() const;

	//--------------------------------------------------------------------------
	/**
	 * メッシュの設定
	 * @param mesh メッシュ
	 */
	virtual void setMesh(Mesh* mesh);

	//--------------------------------------------------------------------------
	/**
	 * フォグの設定
	 * @param fog フォグ
	 */
	virtual void setFog(Fog* fog){ fog_ = fog; }

	//--------------------------------------------------------------------------
	/**
	 * カメラの設定
	 * @param camera カメラ
	 */
	virtual void setCamera(Camera* camera){ camera_ = camera; }

	//--------------------------------------------------------------------------
	/**
	 * アンビエントライトの追加
	 * @param ambientLight 追加するライト
	 */
	virtual void addAmbientLight(AmbientLight* ambientLight);

	/**
	 * ディレクショナルライトの追加
	 * @param directionalLight 追加するライト
	 */
	virtual void addDirectionalLight(DirectionalLight* directionalLight);

	//--------------------------------------------------------------------------
	/**
	 * ローカルライトのソート実装
	 */
	virtual int sortLocalLightsImprement(LocalLight* left, LocalLight* right);

private:
	//--------------------------------------------------------------------------
	// コピーコンストラクタの隠蔽
	DrawRequest(const DrawRequest& copy);

	// 代入コピーの隠蔽
	void operator =(const DrawRequest& copy);

	// インスタンス
	static DrawRequest* instance_;
	// アンビエントライト
	ArrayList<AmbientLight*> ambientLights_;
	// ディレクショナルライト
	ArrayList<DirectionalLight*> directionalLights_;
	// ローカルライト
	ArrayList<LocalLight*> localLights_;
	// フォグ
	Fog* fog_;
	// カメラ
	Camera* camera_;
	// メッシュ
	Mesh* mesh_;
	// シーンノード
	SceneNode* sceneNode_;
	// モデル
	Model* model_;
	// メッシュデータ
	MeshData* meshData_;
	// マテリアル
	Material* material_;
	// 前のメッシュ
	Mesh* preMesh_;
	// 前のシーンノード
	SceneNode* preSceneNode_;
	// 前のモデル
	Model* preModel_;
	// 前のメッシュデータ
	MeshData* preMeshData_;
	// 前のマテリアル
	Material* preMaterial_;

};

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