// Aqsis
// Copyright (c) 1997 - 2001, Paul C. Gregory
//
// Contact: pgregory@aqsis.com
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation; either
// version 2 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
// General Public License for more details.
//
// You should have received a copy of the GNU 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

/**
 * Copyright (C) 2006-2007  NTT DATA CORPORATION
 * 
 * Version: 1.0.0 2007/04/01
 *  
 */
package net.cellcomputing.himawari.shadervm;

import static net.cellcomputing.himawari.library.EqIntIndex.SHD_var_varying;
import static net.cellcomputing.himawari.library.EqIntIndex.SHD_var_varying_current;
import static net.cellcomputing.himawari.library.EqIntIndex.SHD_var_varying_peak;
import net.cellcomputing.himawari.accessory.STLArray;
import net.cellcomputing.himawari.accessory.STLVector;
import net.cellcomputing.himawari.accessory.primitive.p_String;
import net.cellcomputing.himawari.accessory.primitive.p_float;
import net.cellcomputing.himawari.library.CqStats;
import net.cellcomputing.himawari.library.EqVariableClass;
import net.cellcomputing.himawari.library.EqVariableType;
import net.cellcomputing.himawari.library.types.CqColor;
import net.cellcomputing.himawari.library.types.CqMatrix;
import net.cellcomputing.himawari.library.types.CqVector3D;

/**
 *  Varying variable templatised by type.
 *  タイプによってテンプレート化された
 *  可変の変数を持つShaderDataの抽象クラス
 * @author NTT DATA Corporation
 */
abstract strictfp class CqShaderVariableVarying<R> extends CqShaderVariable {
	//protected  STLVector<R>	m_aValue;	///< Simgle uniform value of the appropriate type.
	protected  STLArray<R>	m_aValue;	///< Simgle uniform value of the appropriate type.
	protected  EqVariableType T;	//Generics T
	//protected  R	m_temp_R; //maybe unnecessary 

	/**
	 * コンストラクタ
	 * 統計情報を更新する
	 * @param T Generics T
	 */
	public CqShaderVariableVarying( EqVariableType T) 
	{
		super();
		this.T = T;
//		m_aValue.resize( 1 );子クラスに委譲する
		
		CqStats.STATS_INC( SHD_var_varying );
		CqStats.STATS_INC( SHD_var_varying_current );
		int cvVar = CqStats.STATS_GETI( SHD_var_varying_current );
		int cPeak = CqStats.STATS_GETI( SHD_var_varying_peak );
		CqStats.STATS_SETI( SHD_var_varying_peak, cvVar > cPeak ? cvVar : cPeak );
	}
	/**
	 * コンストラクタ
	 * 統計情報を更新する
	 * @param strName 
	 * @param T Generics T
	 */
	public CqShaderVariableVarying( final String strName,EqVariableType T){
		this(strName,false,T);
	}
	/**
	 * コンストラクタ
	 * 統計情報を更新する
	 * @param strName 
	 * @param fParameter
	 * @param T Generics T
	 */
	public CqShaderVariableVarying( final String strName, boolean fParameter,EqVariableType T)
	{
		super( strName, fParameter );
//		m_aValue.resize( 1 );子クラスに委譲する
		this.T = T;
		CqStats.STATS_INC( SHD_var_varying );
		CqStats.STATS_INC( SHD_var_varying_current );
		int cvVar = CqStats.STATS_GETI( SHD_var_varying_current );
		int cPeak = CqStats.STATS_GETI( SHD_var_varying_peak );
		CqStats.STATS_SETI( SHD_var_varying_peak, cvVar > cPeak ? cvVar : cPeak );
	}
	
    /**
     * コンストラクタ
     * 統計情報を更新し、第2引数valの値をコピーする
     * @param strName
     * @param val ShaderDataの先頭の値に代入する
     * @param T Generics T
     */
	public CqShaderVariableVarying( final String strName,final R val ,EqVariableType T)
	{
		super( strName );
		this.T = T;
		//追加
		if(val instanceof CqColor){
			m_aValue = (STLArray<R>) new STLArray<CqColor>(CqColor.class);
			m_aValue.resize( 1 );
			((CqColor)m_aValue.elementAt(0)).assignment((CqColor)val);
		}else if(val instanceof CqVector3D){
			m_aValue = (STLArray<R>) new STLArray<CqVector3D>(CqVector3D.class);
			m_aValue.resize( 1 );
			((CqVector3D)m_aValue.elementAt(0)).assignment((CqVector3D)val);
		}else if(val instanceof CqMatrix){
			m_aValue = (STLArray<R>) new STLArray<CqMatrix>(CqMatrix.class);
			m_aValue.resize( 1 );
			((CqMatrix)m_aValue.elementAt(0)).assignment((CqMatrix)val);
		}else if(val instanceof p_float){
			m_aValue = (STLArray<R>) new STLArray<p_float>(p_float.class);
			m_aValue.resize( 1 );
			((p_float)m_aValue.elementAt(0)).value = ((p_float)val).value;
		}else if(val instanceof p_String){
			m_aValue = (STLArray<R>) new STLArray<p_String>(p_String.class);
			m_aValue.resize( 1 );
			((p_String)m_aValue.elementAt(0)).value = ((p_String)val).value;
		}
//		if(val instanceof CqColor){
//			m_aValue = (STLVector<R>) new STLVector<CqColor>(CqColor.class);
//			m_aValue.resize( 1 );
//			((CqColor)m_aValue.elementAt(0)).assignment((CqColor)val);
//		}else if(val instanceof CqVector3D){
//			m_aValue = (STLVector<R>) new STLVector<CqVector3D>(CqVector3D.class);
//			m_aValue.resize( 1 );
//			((CqVector3D)m_aValue.elementAt(0)).assignment((CqVector3D)val);
//		}else if(val instanceof CqMatrix){
//			m_aValue = (STLVector<R>) new STLVector<CqMatrix>(CqMatrix.class);
//			m_aValue.resize( 1 );
//			((CqMatrix)m_aValue.elementAt(0)).assignment((CqMatrix)val);
//		}else if(val instanceof p_float){
//			m_aValue = (STLVector<R>) new STLVector<p_float>(p_float.class);
//			m_aValue.resize( 1 );
//			((p_float)m_aValue.elementAt(0)).value = ((p_float)val).value;
//		}else if(val instanceof p_String){
//			m_aValue = (STLVector<R>) new STLVector<p_String>(p_String.class);
//			m_aValue.resize( 1 );
//			((p_String)m_aValue.elementAt(0)).value = ((p_String)val).value;
//		}
		//--ここまで
		
		CqStats.STATS_INC( SHD_var_varying );
		CqStats.STATS_INC( SHD_var_varying_current );
		int cvVar = CqStats.STATS_GETI( SHD_var_varying_current );
		int cPeak = CqStats.STATS_GETI( SHD_var_varying_peak );
		CqStats.STATS_SETI( SHD_var_varying_peak, cvVar > cPeak ? cvVar : cPeak );
	}
	
	/**
	 * コピーコンストラクタ
	 * @param val コピー元
	 * @param T Generics T
	 */
	public CqShaderVariableVarying( final CqShaderVariableVarying<R> val ,EqVariableType T)
	{
		super( val );
		this.T = T;
		//子クラスに委譲
//		m_aValue.resize( val.m_aValue.size() );
//		m_aValue.assign( val.m_aValue.begin(), val.m_aValue.begin() );
//		m_aValue.clear();
		//ここまで
		
		CqStats.STATS_INC( SHD_var_varying );
		CqStats.STATS_INC( SHD_var_varying_current );
		int cvVar = CqStats.STATS_GETI( SHD_var_varying_current );
		int cPeak = CqStats.STATS_GETI( SHD_var_varying_peak );
		CqStats.STATS_SETI( SHD_var_varying_peak, cvVar > cPeak ? cvVar : cPeak );
	}
	
	/**
	 * デストラクタ
	 */
	public void destruct()
	{
		super.destruct();
		CqStats.STATS_DEC( SHD_var_varying_current );
	}
	
	/*
	 * 子クラスに委譲する。
	 * 理由は R 型をインスタンス化できないため
	public	void	Initialise( final int uGridRes, final int vGridRes )
	{
		R Def;
		
		if ( m_aValue.size() > 0 )
			Def = m_aValue.elementAt(0);
		//---変更
//		m_aValue.assign( (( uGridRes + 1 ) * ( vGridRes + 1 )), Def );
		int limit = ( uGridRes + 1 ) * ( vGridRes + 1 );
		m_aValue.setSize(limit);
		for(int i=0;i < limit ;i++ ){
//			m_aValue.setElementAt(Def,i);
		}
		//ここまで
		CqStats.STATS_INC( SHD_Var_varying_init );
	}*/
	
	/**
	 * ShaderDataの持つVectorの長さを変更する
	 * @param size 変更後のサイズ
	 */
	public	void	SetSize( final int size )
	{
		m_aValue.resize( size );
	}
	
	/**
	 * 常に失敗する関数
	 */
	public	void	GetFloat( p_float res, int index)
	{
		assert( false );
	}
	
	/**
	 * 常に失敗する関数
	 */
	public	void	GetString( p_String res, int index)
	{
		assert( false );
	}
	/**
	 * 常に失敗する関数
	 */
	public	void	GetPoint( CqVector3D res, int index)
	{
		assert( false );
	}
	/**
	 * 常に失敗する関数
	 */
	public	void	GetVector( CqVector3D res, int index)
	{
		assert( false );
	}
	/**
	 * 常に失敗する関数
	 */
	public	void	GetNormal( CqVector3D res, int index)
	{
		assert( false );
	}
	/**
	 * 常に失敗する関数
	 */
	public	void	GetColor( CqColor res, int index)
	{
		assert( false );
	}
	/**
	 * 常に失敗する関数
	 */
	public	void	GetMatrix( CqMatrix res, int index)
	{
		assert( false );
	}
	
	/**
	 * 常に失敗する関数
	 */
	public	void	GetFloatPtr( final STLVector<p_float> res )
	{
		assert( false );
	}
	/**
	 * 常に失敗する関数
	 */
	public	void	GetStringPtr( final STLVector<p_String> res )
	{
		assert( false );
	}
	/**
	 * 常に失敗する関数
	 */
	public	void	GetPointPtr( final STLVector<CqVector3D> res )
	{
		assert( false );
	}
	/**
	 * 常に失敗する関数
	 */
	public	void	GetVectorPtr( final STLVector<CqVector3D> res )
	{
		assert( false );
	}
	/**
	 * 常に失敗する関数
	 */
	public	void	GetNormalPtr( final STLVector<CqVector3D> res )
	{
		assert( false );
	}
	/**
	 * 常に失敗する関数
	 */
	public	void	GetColorPtr( final STLVector<CqColor> res )
	{
		assert( false );
	}
	/**
	 * 常に失敗する関数
	 */
	public	void	GetMatrixPtr( final STLVector<CqMatrix> res )
	{
		assert( false );
	}
	
	
	/**
	 * 常に失敗する関数
	 */
	public	void	SetFloat( final float f )
	{
		assert( false );
	}
	/**
	 * 常に失敗する関数
	 */
	public	void	SetString( final String s )
	{
		assert( false );
	}
	/**
	 * 常に失敗する関数
	 */
	public	void	SetPoint( final CqVector3D p )
	{
		assert( false );
	}
	/**
	 * 常に失敗する関数
	 */
	public	void	SetVector( final CqVector3D v )
	{
		assert( false );
	}
	/**
	 * 常に失敗する関数
	 */
	public	void	SetNormal( final CqVector3D n )
	{
		assert( false );
	}
	/**
	 * 常に失敗する関数
	 */
	public	void	SetColor( final CqColor c )
	{
		assert( false );
	}
	/**
	 * 常に失敗する関数
	 */
	public	void	SetMatrix( final CqMatrix m )
	{
		assert( false );
	}
	
	/**
	 * 常に失敗する関数
	 */
	public	void	SetFloat( final float f, int index )
	{
		assert( false );
	}
	/**
	 * 常に失敗する関数
	 */
	public	void	SetString( final String s, int index )
	{
		assert( false );
	}
	/**
	 * 常に失敗する関数
	 */
	public	void	SetPoint( final CqVector3D p, int index )
	{
		assert( false );
	}
	/**
	 * 常に失敗する関数
	 */
	public	void	SetVector( final CqVector3D v, int index )
	{
		assert( false );
	}
	/**
	 * 常に失敗する関数
	 */
	public	void	SetNormal( final CqVector3D n, int index )
	{
		assert( false );
	}
	/**
	 * 常に失敗する関数
	 */
	public	void	SetColor( final CqColor c, int index )
	{
		assert( false );
	}
	/**
	 * 常に失敗する関数
	 */
	public	void	SetMatrix( final CqMatrix m, int index )
	{
		assert( false );
	}
	
	/**
	 * このshaderDataのClassを返す
	 * @return EqVariableClass.class_varyingの値を持つEqVariableClassが返る
	 */
	public	EqVariableClass	Class()
	{
		return ( new EqVariableClass(EqVariableClass.class_varying) );
	}
	/**
	 * このshaderDataのTypeを返す
	 * @return Tの値を持つEqVariableTypeが返る
	 */
	public	EqVariableType	Type()
	{
		return ( T );
	}
	/**
	 * shaderDataの持つVectorの長さが返る
	 * @return shaderDataの持つVectorの長さ
	 */
	public long	Size()
	{
		return ( m_aValue.size() );
	}

	//子クラスに委譲
	public abstract void assignment(final CqShaderVariableVarying<R> From);
	/*
	public	void	assignment( final CqShaderVariableVarying<R> From )
	{
		// use std::vector assignment
//		m_aValue = From.m_aValue;
	}*/
}
