//------------------------------------------------------------------------------
// 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 PRIMITIVE_DRAW_REQUEST_H_
#define PRIMITIVE_DRAW_REQUEST_H_

#include <Graphics/System/GraphicsDeviceObjectHolder.h>

namespace Lamp{

//------------------------------------------------------------------------------
/**
 * プリミティブ描画リクエスト
 */
class PrimitiveDrawRequest{
friend class PrimitiveRenderer;
public:
	//--------------------------------------------------------------------------
	// 生成、破棄
	//--------------------------------------------------------------------------
	/**
	 * コンストラクタ
	 */
	PrimitiveDrawRequest();

	/**
	 * コピーコンストラクタ
	 * @param copy コピー元
	 */
	PrimitiveDrawRequest(const PrimitiveDrawRequest& copy);

	/**
	 * 代入コピー
	 * @param copy コピー元
	 */
	PrimitiveDrawRequest& operator =(const PrimitiveDrawRequest& copy);

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

	//--------------------------------------------------------------------------
	// 頂点数
	//--------------------------------------------------------------------------
	/**
	 * 頂点数の設定
	 * @param vertexCount 頂点数
	 */
	virtual void setVertexCount(int vertexCount);

	/**
	 * 頂点数の取得
	 * @return 頂点数
	 */
	virtual int getVertexCount() const{ return data_->vertexCount_; }

	/**
	 * 頂点サイズの取得
	 * @return 頂点サイズ
	 */
	virtual int getVertexSize() const{
		if(hasColor()){ return sizeof(Vector3) + sizeof(Color4c); }
		else{ return sizeof(Vector3); }
	}

	//--------------------------------------------------------------------------
	// 位置
	//--------------------------------------------------------------------------
	/**
	 * 位置の設定
	 * @param index インデックス
	 * @param position 位置
	 */
	virtual void setPosition(int index, const Vector3& position){
		Assert((index >= 0) && (index < data_->vertexCount_));
		data_->positions_[index] = position;
		data_->vertexBufferChanged_ = true;
	}

	/**
	 * 位置の取得
	 * @param index インデックス
	 * @return 位置
	 */
	virtual const Vector3& getPosition(int index) const{
		Assert((index >= 0) && (index < data_->vertexCount_));
		return data_->positions_[index];
	}

	/**
	 * 位置配列の取得
	 * @return 位置配列
	 */
	virtual const Vector3* getPositionArray() const{ return data_->positions_; }

	//--------------------------------------------------------------------------
	// カラー
	//--------------------------------------------------------------------------
	/**
	 * カラーを有効にするかどうか
	 * @param colorFlag trueならカラーが有効になる
	 */
	virtual void enableColor(bool colorFlag);

	/**
	 * カラーを持つか
	 * @return カラーを持つならtrue
	 */
	virtual bool hasColor() const{ return (data_->colors_ != NULL); }

	/**
	 * カラーの設定
	 * @param index インデックス
	 * @param color カラー
	 */
	virtual void setColor(int index, const Color4c& color){
		Assert(hasColor());
		Assert((index >= 0) && (index < data_->vertexCount_));
		data_->colors_[index] = color;
		data_->vertexBufferChanged_ = true;
	}

	/**
	 * カラーの取得
	 * @param index インデックス
	 * @return カラー
	 */
	virtual const Color4c& getColor(int index) const{
		Assert(hasColor());
		Assert((index >= 0) && (index < data_->vertexCount_));
		return data_->colors_[index];
	}

	/**
	 * カラー配列の取得
	 * @return カラー配列
	 */
	virtual const Color4c* getColorArray() const{ return data_->colors_; }

	//--------------------------------------------------------------------------
	// インデックス
	//--------------------------------------------------------------------------
	/**
	 * 頂点インデックスを持つかどうか
	 * @return 頂点インデックスを持つならtrue
	 */
	virtual bool hasVertexIndices() const{
		return (data_->vertexIndexCount_ != 0);
	}

	/**
	 * 頂点インデックス数の設定
	 * @param vertexIndexCount 頂点インデックス数
	 */
	virtual void setVertexIndexCount(int vertexIndexCount);

	/**
	 * 頂点インデックス数の取得
	 * @return 頂点インデックス数
	 */
	virtual int getVertexIndexCount() const{ return data_->vertexIndexCount_; }

	/**
	 * 頂点インデックスの設定
	 * @param index インデックス
	 * @param vertexIndex 頂点インデックス
	 */
	virtual void setVertexIndex(int index, u_short vertexIndex){
		Assert(hasVertexIndices());
		Assert((index >= 0) && (index < getVertexIndexCount()));
		data_->vertexIndices_[index] = vertexIndex;
		data_->indexBufferChanged_ = true;
	}

	/**
	 * 頂点インデックスの取得
	 * @param index インデックス
	 * @return 頂点インデックス
	 */
	virtual u_short getVertexIndex(int index) const{
		Assert(hasVertexIndices());
		Assert((index >= 0) && (index < getVertexIndexCount()));
		return data_->vertexIndices_[index];
	}

	/**
	 * 頂点インデックス配列の取得
	 * @return 頂点インデックス配列
	 */
	virtual const u_short* getVertexIndexArray(){
		return data_->vertexIndices_;
	}

private:
	//--------------------------------------------------------------------------
	/**
	 * リファレンスの削除
	 * @return リファレンスカウント
	 */
	virtual int removeReference();

	//--------------------------------------------------------------------------
	/**
	 * 頂点バッファの取得
	 * @return 頂点バッファ
	 */
	Direct3DVertexBuffer* getVertexBuffer();

	/**
	 * インデックスバッファの取得
	 * @return インデックスバッファ
	 */
	Direct3DIndexBuffer* getIndexBuffer();

	//--------------------------------------------------------------------------
	/**
	 * データ
	 */
	class Data : public GraphicsDeviceObjectHolder{
	friend class PrimitiveDrawRequest;
	private:
		//----------------------------------------------------------------------
		/**
		 * コンストラクタ
		 */
		Data();

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

		//----------------------------------------------------------------------
		// リファレンスの追加
		virtual int addReference(){
			referenceCount_++;
			return referenceCount_;
		}

		// リファレンスの削除
		virtual int removeReference(){
			referenceCount_--;
			return referenceCount_;
		}

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

		/**
		 * デバイスオブジェクトの削除
		 */
		virtual void deleteGraphicsDeviceObjects(){}

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

		/**
		 * デバイスオブジェクトの無効化
		 */
		virtual void invalidateGraphicsDeviceObjects(){
			SafeRelease(indexBuffer_);
			SafeRelease(vertexBuffer_);
		}

		//----------------------------------------------------------------------
		// 頂点数
		int vertexCount_;
		// 位置
		Vector3* positions_;
		// カラー
		Color4c* colors_;
		// 頂点インデックス数
		int vertexIndexCount_;
		// 頂点インデックス
		u_short* vertexIndices_;
		// 頂点バッファ
		Direct3DVertexBuffer* vertexBuffer_;
		// インデックスバッファ
		Direct3DIndexBuffer* indexBuffer_;
		// リファレンスカウント
		int referenceCount_;
		// 頂点バッファに変更があった
		bool vertexBufferChanged_;
		// インデックスバッファに変更があった
		bool indexBufferChanged_;

	};

	//--------------------------------------------------------------------------
	// メンバ変数
	//--------------------------------------------------------------------------
	/// データ
	Data* data_;

};

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