// 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.library;

import java.util.Iterator;

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.accessory.primitive.p_int;
import net.cellcomputing.himawari.library.types.CqColor;
import net.cellcomputing.himawari.library.types.CqMatrix;
import net.cellcomputing.himawari.library.types.CqVector3D;
import net.cellcomputing.himawari.library.types.CqVector4D;

/**
 * 値のタイプと、idのタイプでテンプレート化された、一定の配列タイプのパラメータ
 * @author NTT DATA Corporation
 */
public strictfp class CqParameterTypedConstantArray<T,SLT> extends CqParameterTyped<T,SLT> {
	private STLVector<T>	m_aValues;
	private EqVariableType I;//C++ではGenericsとして指定されている値
	
	/**
	 * コンストラクタ
	 * @param str 名前
	 * @param count サイズ
	 * @param I Generics I
	 * @param TClass Generics TのClass
	 * @param SLTClass Generics SLTのClass
	 */
	public CqParameterTypedConstantArray(final String str,int count,EqVariableType I,Class<? extends T> TClass,Class<? extends SLT> SLTClass){
		super(str,count,TClass,SLTClass);
		
		m_aValues = new STLVector<T>(TClass,count);
		m_aValues.setSize(count);
		
		this.I = I;
	}
	
	/**
	 * コピーコンストラクタ
	 * @param From コピー元
	 * @param I Generics I
	 */
	public CqParameterTypedConstantArray(CqParameterTypedConstantArray<T,SLT> From,EqVariableType I){
		super(From);
		m_aValues = new STLVector<T>(TClass);
		m_aValues.setSize(From.Count());
		this.I = I;
		if(TClass.equals(CqVector3D.class)){
			for(int i=0; i < From.m_Count ; i++)
				((CqVector3D)m_aValues.elementAt(i)).assignment((CqVector3D)From.m_aValues.elementAt(i));
			
		}else if(TClass.equals(CqVector4D.class)){
			for(int i=0; i < From.m_Count ; i++)
				((CqVector4D)m_aValues.elementAt(i)).assignment((CqVector4D)From.m_aValues.elementAt(i));
		}else if(TClass.equals(CqColor.class)){
			for(int i=0; i < From.m_Count ; i++)
				((CqColor)m_aValues.elementAt(i)).assignment((CqColor)From.m_aValues.elementAt(i));
		}else if(TClass.equals(CqMatrix.class)){
			for(int i=0; i < From.m_Count ; i++)
				((CqMatrix)m_aValues.elementAt(i)).assignment((CqMatrix)From.m_aValues.elementAt(i));
		}else if(TClass.equals(p_float.class)){
			for(int i=0; i < From.m_Count ; i++)
				((p_float)m_aValues.elementAt(i)).value = ((p_float)From.m_aValues.elementAt(i)).value;
		}else if(TClass.equals(p_int.class)){
			for(int i=0; i < From.m_Count ; i++)
				((p_int)m_aValues.elementAt(i)).value = ((p_int)From.m_aValues.elementAt(i)).value;
		}else if(TClass.equals(p_String.class)){
			for(int i=0; i < From.m_Count ; i++)
				((p_String)m_aValues.elementAt(i)).value = ((p_String)From.m_aValues.elementAt(i)).value;
		}
	}
	
	/**
	 * コンストラクタ
	 * Countが省略されている
	 * 
	 * @param name 名前
	 * @param I Genrics I
	 * @param TClass Generics SのClass
	 */
	public CqParameterTypedConstantArray(final String name,EqVariableType I,Class<? extends T> TClass,Class<? extends SLT> SLTClass){
		this(name,1,I,TClass,SLTClass);
	}
	
	/**
	 * デストラクタ
	 */
	public void destruct(){
		super.destruct();
	}
	
	/**
	 * 自分の持つVectorの値を配列として全て返す。
	 * @return Vectorの値がはいっている配列
	 */
	public Object[] pValue() {
        assert( 0 < m_aValues.size() );

		return m_aValues.toArray();
	}
	
	/**
	 * 自分の持つVectorの値を配列として全て返す。
	 * 
	 * @param Index 使用しない
	 * @return Vectorの値がはいっている配列
	 */
	public Object[] pValue(int Index) {
        assert( 0 < m_aValues.size() );

		return m_aValues.toArray();
	}
	
//	nttdata chenge
	public T pValue_get(final int Index ,final int arrayIndex)
	{
		return m_aValues.elementAt(arrayIndex);
	}
	
	/**
	 * Typeの同じクローンを生成して返す
	 * 
	 * @param Name 名前
	 * @param Count 自分の持つVectorの長さ
	 * @return 新しいCqParameter
	 */
	public CqParameter CloneType(String Name, int Count) {
	       return ( new CqParameterTypedConstantArray<T,SLT>( Name, Count, I,TClass,SLTClass ) );
	}
	
	/**
	 * 自分自身と同じ値を持つインスタンスを生成する。
	 */
	public CqParameter Clone() {
	       return ( new CqParameterTypedConstantArray<T, SLT>(this,I) );
	}
	
	/**
	 * EqVariableClassを返す
	 *
	 * @return 自分のEqVariableClass
	 */
	public EqVariableClass Class() {
		return new EqVariableClass(EqVariableClass.class_constant);
	}
	
	/**
	 * 自分のもつEqVariableTypeを返す
	 * (C++ではGenericsで利用されている)
	 * @return EqVariableType
	 */
	public EqVariableType Type() {
		return I;
	}
	
	/**
	 * 空メソッド 
	 */
	public void SetSize(int size) {
		//空メソッド
		
	}
	
	/**
	 * 常に1を返す関数
	 * 
	 * @return 1
	 */
	public int Size() {
		return 1;
	}
	
	/**
	 * 空メソッド
	 */
	public void Clear() {
		//空メソッド		
	}
	
	/**
	 * 空メソッド
	 */
	public void Subdivide(CqParameter pResult1, CqParameter pResult2, boolean u,
			IqSurface pSurface) {
		//空メソッド
	}
	
	/**
	 * IqShaderDataに値を代入する<br>
	 * (親クラスでの説明)<br>
	 * 配列の単一の要素値をそのクラスの適切な補完を用いてグリッドに切り出す(Dice)
	 * 
	 * @param u
	 * @param v
	 * @param pResult 
	 * @param pSurface 使用しない
	 */	
	public void Dice(int u, int v, IqShaderData pResult, IqSurface pSurface) {
//		 Just promote the constant value to varying by duplication.
		assert( pResult.Type().getValue() == Type().getValue() );
       // Note it is assumed that the variable has been
       // initialised to the correct size prior to calling.
       int i;
       long max = Math.max( (long)(u * v), pResult.Size() );
       
       //Genericsに入る型によって場合わけを行う
       if(TClass.equals(CqMatrix.class)){
           for ( i = 0; i < max; i++ ){
               pResult.SetValue( (CqMatrix)pValue_get( 0 , 0 ), i );
           }
       }else if(TClass.equals(CqVector3D.class)){
           for ( i = 0; i < max; i++ ){
               pResult.SetValue( (CqVector3D) pValue_get( 0 , 0 ), i );
           }
       }else if(TClass.equals(CqVector4D.class)){
           for ( i = 0; i < max; i++ ){
               pResult.SetValue(new CqVector3D(((CqVector4D)( pValue_get( 0 , 0 )))), i );
           }
       }else if(TClass.equals(CqColor.class)){
           for ( i = 0; i < max; i++ ){
               pResult.SetValue( (CqColor) pValue_get( 0 , 0 ), i );
           }
       }else if(TClass.equals(p_float.class)){
           for ( i = 0; i < max; i++ ){
               pResult.SetValue( ((p_float) pValue_get( 0 , 0 )).value, i );
           }
       }else if(TClass.equals(p_int.class)){
           for ( i = 0; i < max; i++ ){
               pResult.SetValue( ((p_int) pValue_get( 0 , 0 )).value, i );
           }
       }else if(TClass.equals(p_String.class)){
           for ( i = 0; i < max; i++ ){
               pResult.SetValue( ((p_String) pValue_get( 0 , 0 )).value, i );
           }
       }
	}
	
	/**
	 * IqShaderDataに自分が持つVectorのArrayIndexで指定された場所の値を代入する。
	 * Max(u*v,pResult.size())分だけIqShaderDataにコピーする
	 * <br>
	 * (親クラスでの説明)<br>
	 * 配列の単一の要素値をそのクラスの適切な補完を用いてグリッドに切り出す(Dice)
	 * 
	 * @param u
	 * @param v
	 * @param pResult 
	 * @param pSurface 使用しない
	 * @param ArrayIndex 指定する場所
	 */	
	public void DiceOne(int u, int v, IqShaderData pResult, IqSurface pSurface,
			int ArrayIndex) {
//		 Just promote the constant value to varying by duplication.
		assert( Count() > ArrayIndex );
		assert( pResult.Type().getValue() == Type().getValue() );
        // Note it is assumed that the variable has been
        // initialised to the correct size prior to calling.
        int i;
        long max = Math.max( (long)(u * v), pResult.Size() );
        
        //Genericsに入る型によって場合わけを行う
        if(TClass.equals(CqMatrix.class)){
            for ( i = 0; i < max; i++ ){
                pResult.SetValue( (CqMatrix)pValue_get( 0 , ArrayIndex ), i );
            }
        }else if(TClass.equals(CqVector3D.class)){
            for ( i = 0; i < max; i++ ){
                pResult.SetValue( (CqVector3D)pValue_get( 0 , ArrayIndex ), i );
            }
        }else if(TClass.equals(CqVector4D.class)){
            for ( i = 0; i < max; i++ ){
                pResult.SetValue(new CqVector3D(((CqVector4D)( pValue_get( 0 , ArrayIndex )))), i );
            }
        }else if(TClass.equals(CqColor.class)){
            for ( i = 0; i < max; i++ ){
                pResult.SetValue( (CqColor)pValue_get( 0 , ArrayIndex ), i );
            }
        }else if(TClass.equals(p_float.class)){
            for ( i = 0; i < max; i++ ){
                pResult.SetValue( ((p_float) pValue_get( 0 , ArrayIndex )).value, i );
            }
        }else if(TClass.equals(p_int.class)){
            for ( i = 0; i < max; i++ ){
                pResult.SetValue( ((p_int) pValue_get( 0 , ArrayIndex )).value, i );
            }
        }else if(TClass.equals(p_String.class)){
            for ( i = 0; i < max; i++ ){
                pResult.SetValue( ((p_String) pValue_get( 0 , ArrayIndex )).value, i );
            }
        }
	}
	/**
	 * CqParameterTypedで定義されているもの
	 * 引数で指定したインスタンスのVectorから、指定した値を
	 * 自分自身のVectorの指定した位置にコピーを行う
	 * 
	 * @param pFrom コピー元インスタンス
	 * @param idxTarget コピー先の配列番号。
	 * @param idxSource コピー元の配列番号
	 */
	public void SetValue(CqParameter pFrom, int idxTarget, int idxSource){
		assert( pFrom.Type().getValue() == Type().getValue() );
		
        CqParameterTyped<T, SLT> pFromTyped = (CqParameterTyped<T, SLT>)( pFrom );
        T tmp = (T)pValue_get( idxTarget , 0 );//ポインタなので値を取り出す
        if(tmp instanceof CqMatrix){
        	((CqMatrix)tmp).assignment((CqMatrix)(pFromTyped.pValue_get( idxSource , 0 )));
        }else if(tmp instanceof CqVector3D){
        	((CqVector3D)tmp).assignment((CqVector3D)(pFromTyped.pValue_get( idxSource , 0 )));
        }else if(tmp instanceof CqVector4D){
        	((CqVector4D)tmp).assignment((CqVector4D)(pFromTyped.pValue_get( idxSource , 0 )));
        }else if(tmp instanceof CqColor){
        	((CqColor)tmp).assignment((CqColor)(pFromTyped.pValue_get( idxSource , 0 )));
        }else if(tmp instanceof p_float){
        	((p_float)tmp).value = ((p_float)(pFromTyped.pValue_get( idxSource , 0 ))).value;
        }else if(tmp instanceof p_int){
        	((p_int)tmp).value = ((p_int)(pFromTyped.pValue_get( idxSource , 0 ))).value;
        }else if(tmp instanceof p_String){
        	((p_String)tmp).value = ((p_String)(pFromTyped.pValue_get( idxSource , 0 ))).value;
        }
	}
	
	/**
	 * イコール演算子
	 * 代入元が持つVectorの値を全て自分自身のVectorにコピーする
	 * 
	 * @param From 代入元インスタンス
	 * @return 自分自身
	 */
    public CqParameterTypedConstantArray<T,SLT> assignment(final CqParameterTypedConstantArray<T,SLT> From )
    {
        m_aValues.resize( From.m_aValues.size() );
        int i2 = 0;
        Iterator<T> i = From.m_aValues.iterator();
        if(TClass.equals(CqMatrix.class)){
        	while(i.hasNext()){
        		((CqMatrix)m_aValues.elementAt(i2)).assignment((CqMatrix)i.next());
        		i2++;
        	}
        }else if(TClass.equals(CqVector3D.class)){
        	while(i.hasNext()){
        		((CqVector3D)m_aValues.elementAt(i2)).assignment((CqVector3D)i.next());
        		i2++;
        	}
        }else if(TClass.equals(CqVector4D.class)){
        	while(i.hasNext()){
        		((CqVector4D)m_aValues.elementAt(i2)).assignment((CqVector4D)i.next());
        		i2++;
        	}
        }else if(TClass.equals(CqColor.class)){
        	while(i.hasNext()){
        		((CqColor)m_aValues.elementAt(i2)).assignment((CqColor)i.next());
        		i2++;
        	}
        }else if(TClass.equals(p_int.class)){
        	while(i.hasNext()){
        		((p_int)m_aValues.elementAt(i2)).value = ((p_int)i.next()).value;
        		i2++;
        	}
        }else if(TClass.equals(p_float.class)){
        	while(i.hasNext()){
        		((p_float)m_aValues.elementAt(i2)).value = ((p_float)i.next()).value;
        		i2++;
        	}
        }else if(TClass.equals(p_String.class)){
        	while(i.hasNext()){
        		((p_String)m_aValues.elementAt(i2)).value = ((p_String)i.next()).value;
        		i2++;
        	}
        }
        return ( this );
    }
	
    /* Static constructor, to allow type free parameter construction.
     * \param strName Character pointer to new parameter name.
     * \param Count Integer array size.
     */
    /**
	 * static コンストラクタ
	 * コンストラクタと同様に利用できる
	 */
     public static	<T,SLT> CqParameter	Create( final String strName, int Count,EqVariableType I,Class TClass,Class SLTClass)
    {
        return ( new CqParameterTypedConstantArray<T,SLT>( strName, Count ,I,TClass,SLTClass) );
    }
 	
     /**
 	 * static コンストラクタ
 	 * コンストラクタと同様に利用できる(count省略系)
 	 */
     
     public static	<T,SLT> CqParameter	Create( final String strName,EqVariableType I,Class TClass,Class SLTClass)
     {
    	 return CqParameterTypedConstantArray.<T,SLT>Create(strName,1,I,TClass,SLTClass);
     }
}
