// 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.*;
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.IqShaderData;
import net.cellcomputing.himawari.library.types.CqColor;
import net.cellcomputing.himawari.library.types.CqMatrix;
import net.cellcomputing.himawari.library.types.CqVector3D;

/**
 * Uniform variable templatised by type.
 * Genericsタイプによりテンプレート化された
 * 単一の変数を持つシェーダデータ
 * @author NTT DATA Corporation
 */
abstract strictfp class CqShaderVariableUniform<R> extends CqShaderVariable {


	protected  R	m_Value;	///< Simgle uniform value of the appropriate type.
	protected  EqVariableType T;	//Generics T
	
	/**
	 * コンストラクタ
	 * 統計情報を更新する
	 * @param T Generics T
	 */
	public CqShaderVariableUniform(EqVariableType T){
	    	super();
	        this.T = T;
	    	CqStats.STATS_INC( SHD_var_uniform );
	        CqStats.STATS_INC( SHD_var_uniform_current );
	        int cvUni = CqStats.STATS_GETI( SHD_var_uniform_current );
	        int cPeak = CqStats.STATS_GETI( SHD_var_uniform_peak );
	        CqStats.STATS_SETI( SHD_var_uniform_peak, cvUni > cPeak ? cvUni : cPeak );
	    }
	/**
	 * コンストラクタ
	 * 統計情報を更新する
	 * @param strName 
	 * @param fParameter
	 * @param T Generics T
	 */
	  public   CqShaderVariableUniform(final String strName, boolean fParameter,EqVariableType T){
	    	super( strName, fParameter );
	    	 this.T =T;
	    	CqStats.STATS_INC( SHD_var_uniform );
	    	CqStats.STATS_INC( SHD_var_uniform_current );
	        int cvUni = CqStats.STATS_GETI( SHD_var_uniform_current );
	        int cPeak = CqStats.STATS_GETI( SHD_var_uniform_peak );
	        CqStats.STATS_SETI( SHD_var_uniform_peak, cvUni > cPeak ? cvUni : cPeak );
	    }
	    
	  /**
	   * コンストラクタ
	   * 統計情報を更新する
	   * @param strName
	   * @param T Generics T
	   */
	    public CqShaderVariableUniform(final String strName,EqVariableType T){
	    	this(strName,false,T);
	    }
	    
	    /**
	     * コンストラクタ
	     * 統計情報を更新し、第2引数valの値をコピーする
	     * @param strName
	     * @param val
	     * @param T
	     */
	    public CqShaderVariableUniform( final String strName, final R val ,EqVariableType T)
	    {
	    	super(strName);
	    	this.T = T;
//	    	m_Value = val;
	    	
	    	if(val instanceof p_float){
	    		m_Value = (R)new p_float(((p_float)val).value);
	    	}else if(val instanceof CqMatrix){
	    		m_Value = (R)new CqMatrix();
	    		((CqMatrix)m_Value).assignment((CqMatrix)val);
	    	}else if(val instanceof CqVector3D){
	    		m_Value = (R)new CqVector3D();
	    		((CqVector3D)m_Value).assignment((CqVector3D)val);
	    	}else if(val instanceof p_String){
	    		m_Value = (R)new p_String(((p_String)val).value);
	    	}else if(val instanceof CqColor){
	    		m_Value = (R)new CqColor();
	    		((CqColor)m_Value).assignment((CqColor)val);
	    	}
	    	
	    	
	    	CqStats.STATS_INC( SHD_var_uniform );
	    	CqStats.STATS_INC( SHD_var_uniform_current );
	        int cvUni = CqStats.STATS_GETI( SHD_var_uniform_current );
	        int cPeak = CqStats.STATS_GETI( SHD_var_uniform_peak );
	        CqStats.STATS_SETI( SHD_var_uniform_peak, cvUni > cPeak ? cvUni : cPeak );

	    }
	    /**
	     * コピーコンストラクタ
	     * @param val
	     * @param T Generics T
	     */
	    public CqShaderVariableUniform( final CqShaderVariableUniform<R> val ,EqVariableType T)
	    {
	    	super(val);
	    	this.T = T;
	    	//m_Value = val.m_Value;
	    	
	    	if(val.m_Value instanceof p_float){
	    		m_Value = (R)new p_float(((p_float)val.m_Value).value);
	    	}else if(val.m_Value instanceof CqMatrix){
    			m_Value = (R)new CqMatrix();
	    		((CqMatrix)m_Value).assignment((CqMatrix)val.m_Value);
	    	}else if(val.m_Value instanceof CqVector3D){
    			m_Value = (R)new CqVector3D();
	    		((CqVector3D)m_Value).assignment((CqVector3D)val.m_Value);
	    	}else if(val.m_Value instanceof p_String){
    			m_Value = (R)new p_String(((p_String)val.m_Value).value);
	    	}else if(val.m_Value instanceof CqColor){
    			m_Value = (R)new CqColor();
	    		((CqColor)m_Value).assignment((CqColor)val.m_Value);
	    	}
	    	
	    	CqStats.STATS_INC( SHD_var_uniform );
	    	CqStats.STATS_INC( SHD_var_uniform_current );
	        int cvUni = CqStats.STATS_GETI( SHD_var_uniform_current );
	        int cPeak = CqStats.STATS_GETI( SHD_var_uniform_peak );
	        CqStats.STATS_SETI( SHD_var_uniform_peak, cvUni > cPeak ? cvUni : cPeak );
	    }
	    
	    /**
	     * デストラクタ
	     */
	    public void destruct()
	    {
	    	CqStats.STATS_DEC( SHD_var_uniform_current );
	        super.destruct();
	    }
	    
	    /**
	     * イニシャライザ。
	     * 統計情報を更新する。
	     */
	    public 	void	Initialise( final int uGridRes, final int vGridRes )
	    {
	    	CqStats.STATS_INC( SHD_var_uniform_init );
	    }
	    
	    /**
	     * 空メソッド
	     * 
	     * @param size
	     */
	    public 	void	SetSize( final int 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( STLVector<p_float> res )
	    {
	        assert( false );
	    }
	    /**
	     * 常に失敗する関数
	     */
	    public	void	GetStringPtr( STLVector<p_String> res )
	    {
	        assert( false );
	    }
	    /**
	     * 常に失敗する関数
	     */
	    public	void	GetPointPtr( STLVector<CqVector3D> res )
	    {
	        assert( false );
	    }
	    /**
	     * 常に失敗する関数
	     */
	    public	void	GetVectorPtr( STLVector<CqVector3D> res )
	    {
	        assert( false );
	    }
	    /**
	     * 常に失敗する関数
	     */
	    public	void	GetNormalPtr( STLVector<CqVector3D> res )
	    {
	        assert( false );
	    }
	    /**
	     * 常に失敗する関数
	     */
	    public	void	GetColorPtr( STLVector<CqColor> res )
	    {
	        assert( false );
	    }
	    /**
	     * 常に失敗する関数
	     */
	    public	void	GetMatrixPtr( 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 );
	    }

	    /**
	     * SetFloatを呼び出す
	     */
	    public	void	SetFloat( final float f, int index )
	    {
	        SetFloat( f );
	    }
	    /**
	     * SetStringを呼び出す
	     */
	    public	void	SetString( final String s, int index )
	    {
	        SetString( s );
	    }
	    /**
	     * SetPointを呼び出す
	     */
	    public	void	SetPoint( final CqVector3D p, int index )
	    {
	        SetPoint( p );
	    }
	    /**
	     * SetVectorを呼び出す
	     */
	    public	void	SetVector( final CqVector3D v, int index )
	    {
	        SetVector( v );
	    }
	    /**
	     * SetNormalを呼び出す
	     */
	    public	void	SetNormal( final CqVector3D n, int index )
	    {
	        SetNormal( n );
	    }
	    /**
	     * SetColorを呼び出す
	     */
	    public	void	SetColor( final CqColor c, int index )
	    {
	        SetColor( c );
	    }
	    /**
	     * SetMatrixを呼び出す
	     */
	    public	void	SetMatrix( final CqMatrix m, int index )
	    {
	        SetMatrix( m );
	    }

	    /** 
	     * Set the all SIMD data ased on a state vector, only indexes whose bit is set are modified.
	     * 変更されたindexの全てのSIMDデータを渡された状態にVectorセットする
	     * @param pVal The stack entry to assign. スタックにアサインするIqShaderData
	     * @param index Integer SIMD index. SIMDのindex
	     */
	    public	void	SetValueFromVariable( final IqShaderData pVal, int index )
	    {
	        SetValueFromVariable( pVal );
	    }
	    /** 
	     * Copy the values from the passed variable into this, taking into account any class differences.
	     * クラスの相違を考慮して、渡された変数から、自分自身に値をコピーする。
	     * 
	     * @param pVal The variable to copy from.
	     */
	    public	void	SetValueFromVariable( final IqShaderData pVal )
	    {
	        assert( false );
	    }
	    
	    /**
	     * 自分のEqVariableClassを返す
	     * @return 自分のEqVariableClass
	     */
	    public	EqVariableClass	Class()
	    {
	        return (new EqVariableClass( EqVariableClass.class_uniform ));
	    }
	    /**
	     * 自分のEqVariableTypeを返す
	     * @return 自分のEqVariableType
	     */
	    public	EqVariableType	Type()
	    {
	        return ( T );
	    }
	    
	    /**
	     * 常に1を返す関数
	     * @return 1
	     */
	    public long	Size()
	    {
	        return ( 1 );
	    }

	    /**
	     * 代入演算子のオーバーロード
	     * @param From 
	     */
	    public	void assignment( final CqShaderVariableUniform<R> From )
	    {
//	        m_Value = From.m_Value;
	    	if(From.m_Value instanceof p_float){
	    		((p_float)m_Value).value = ((p_float)From.m_Value).value;
	    	}else if(From.m_Value instanceof CqMatrix){
	    		((CqMatrix)m_Value).assignment((CqMatrix)From.m_Value);
	    	}else if(From.m_Value instanceof CqVector3D){
	    		((CqVector3D)m_Value).assignment((CqVector3D)From.m_Value);
	    	}else if(From.m_Value instanceof p_String){
	    		((p_String)m_Value).value = ((p_String)From.m_Value).value;
	    	}else if(From.m_Value instanceof CqColor){
	    		((CqColor)m_Value).assignment((CqColor)From.m_Value);
	    	}
	    }

}
