// 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 net.cellcomputing.himawari.library.types.CqMatrix;
import net.cellcomputing.himawari.util.HimawariLogger;

import static net.cellcomputing.himawari.library.EqModeBlock.*;

/**
 * Abstract base class to handle the current context of the renderer,
 * stores information about the current scoping and previous contexts.
 * 
 * レンダラーの現在の背景を扱うために基底クラスを抜き取って、
 * 現在の見るのと前のコンテキストに関する情報を保存します。
 * 
 * @author NTT DATA Corporation
 */
public strictfp class CqModeBlock {	
			
	    /**
	     * デフォルトコンストラクタ
	     */
		public CqModeBlock(){}
		
		/**
		 * 初期値を与えられた場合のコンストラクタ<br>
		 * 
		 * @param pconParent 前のコンテキスト
	     */
		public CqModeBlock( final CqModeBlock pconParent)
		{
			m_pattrCurrent = null;
	        m_ptransCurrent = null;
	        m_pconParent = pconParent;
	        m_modetype.setValue(Outside);
		}
		
		/**
		 * 初期値を2つ与えられた場合のコンストラクタ
		 * 
		 * @param pconParent	 前のコンテキスト
		 * @param modetype	モードタイプ
		 */
		public CqModeBlock( final CqModeBlock pconParent, int modetype )
		{
			m_pattrCurrent = null;
	        m_ptransCurrent = null;
	        m_pconParent = pconParent;
	        m_modetype.setValue(modetype);
		}
		
		/**
		 *　デストラクタ。<br>
		 *　派生クラスでオーバーライドされる。 
		 */
		public void destruct(){};

		//***********************************************************************************
		//*  Note: These inline functions are defined here to allow full definition of all
		//*		 required classes first.
		//*		これらのインライン機能は、必要なるクラス全てを完全に定義するため、最初に定義しておく。
		//************************************************************************************
		
		/** 
		 * Create a new main context, and link it to the current one.<br>
		 * 　メインコンテキストを新しく作成し、現在のコンテキストとリンクさせる。
		 * 
		 * @return	新しいコンテキスト	
		 */
		public CqModeBlock BeginMainModeBlock()
		{
		   return  new CqMainModeBlock( this );
		}

		/**
		 * Create a new frame context, and link it to the current one.<br>
		 * 	フレームコンテキストを新しく作成し、現在のコンテキストとリンクさせる。
		 *  
		 * @return a pointer to the new context.<br>
		 */
	    public CqModeBlock	BeginFrameModeBlock()
	    {
	    	return new CqFrameModeBlock( this );
	    }
	    
	    /** 
	     * Create a new world context, and link it to the current one.<br>
	     * 	ワールドコンテキストを新しく作成し、現在のコンテキストとリンクさせる。
	     * 
	     * @return 新しいコンテキスト。
	     * 
	     */
	    public CqModeBlock	BeginWorldModeBlock()
	    {
	        return new CqWorldModeBlock( this );
	    }
	    
	    /**
	     *  Create a new attribute context, and link it to the current one.<br>
	     * 	アトリビュートコンテキストを新しく作成し、現在のコンテキストとリンクさせる。
	     * 
	     * @return 新しいコンテキスト。
	     */
	    public CqModeBlock	BeginAttributeModeBlock()
	    {
	    	return new CqAttributeModeBlock( this );
	    }

	    /**
	     * Create a new transform context, and link it to the current one.<br>
	     * 	トランスフォームコンテキストを新しく作成し、現在のコンテキストとリンクさせる。
	     * 
	     * @return 新しいコンテキスト。
	     */
	    public CqModeBlock	BeginTransformModeBlock()
	    {
	    	return new CqTransformModeBlock( this );
	    }
	    
	    /**
	     *  Create a new solid context, and link it to the current one.<br>
	     * 	ソリッドコンテキストを新しく作成し、現在のコンテキストとリンクさせる。
	     * 
	     * @param	type
	     * @return	新しいコンテキスト。 
	     */
	    public CqModeBlock	BeginSolidModeBlock( String type )
	    {
	    	return new CqSolidModeBlock( type, this );
	    }
	    
	    
	    /** 
	     * Create a new object context, and link it to the current one.<br>
	     * 	オブジェクトコンテキストを新しく作成し、現在のコンテキストとリンクさせる。
	     * 	
	     * @return 新しいコンテキスト。
	     */
	    public CqModeBlock	BeginObjectModeBlock()
	    {
	    	return new CqObjectModeBlock( this );
	    }

	    /**
	     * Create a new motion context, and link it to the current one.<br>
	     * 	新しいモーションのコンテキストを作成し、そして現在のコンテキストとリンクさせる。
	     * 
	     * @param	N
	     * @param	times[]
	     * @return	新しいコンテキスト。
	     */
	    public CqModeBlock	BeginMotionModeBlock( int N, float times[] )
	    {
	    	return new CqMotionModeBlock( N, times, this );
	    }

	    /** 
	     * Delete the main context, overridable per derived class.<br>
	     * 	メインのコンテキストを消去。 派生クラスでオーバライドされる。
	     * 
	     * @warning このクラスレベルでこのメソッドが呼ばれた場合、ログエラーを出力。
	     */
	    public void	EndMainModeBlock()
	    {
	        logInvalidNesting();
	    }
	    /** 
	     * Delete the frame context, overridable per derived class.<br>
	     * 	フレームのコンテキストを消去。 派生クラスでオーバライドされる。
	     * 
	     * @warning このクラスレベルでこのメソッドが呼ばれた場合、ログエラーを出力。
	     */
	    
	    public	void	EndFrameModeBlock()
	    {
	        logInvalidNesting();
	    }
	    
	    /** 
	     * Delete the world context, overridable per derived class.<br>
	     * 	ワールドのコンテキストを消去。　派生クラスでオーバライドされる。
	     * 
	     * @warning このクラスレベルでこのメソッドが呼ばれた場合、ログエラーを出力。
	     */
	    public	void	EndWorldModeBlock()
	    {
	        logInvalidNesting();
	    }
	    
	    /** 
	     * Delete the Attribute context, overridable per derived class.<br>
	     * 	アトリビュートのコンテキストを消去。　派生クラスでオーバライドされる。
	     * 
	     * @warning このクラスレベルでこのメソッドが呼ばれた場合、ログエラーを出力。
	     */
	    public	void	EndAttributeModeBlock()
	    {
	        logInvalidNesting();
	    }
	    
	    /** 
	     * Delete the Transform context, overridable per derived class.<br>
	     * 	トランスフォームのコンテキストを消去。　派生クラスでオーバライドされる。
	     * 
	     * @warning このクラスレベルでこのメソッドが呼ばれた場合、ログエラーを出力。
	     */
	    public	void	EndTransformModeBlock()
	    {
	        logInvalidNesting();
	    }
	    
	    /**
	     * Delete the SolidMode context, overridable per derived class.<br>
	     * 	ソリッドモデルのコンテキストを消去。　派生クラスでオーバライドされる。
	     * 
	     * @warning このクラスレベルでこのメソッドが呼ばれた場合、ログエラーを出力。
	     */
	    public	void	EndSolidModeBlock()
	    {
	        logInvalidNesting();
	    }
	    
	    /** 
	     * Delete the ObjectMode context, overridable per derived class.<br>
	     * 	オブジェクトモデルのコンテキストを消去。　派生クラスでオーバライドされる。
	     * 
	     * @warning このクラスレベルでこのメソッドが呼ばれた場合、ログエラーを出力。
	     */
	    public	void	EndObjectModeBlock()
	    {
	        logInvalidNesting();
	    }
	    
	    /** 
	     * Delete the MotionMode context, overridable per derived class.<br>
	     * 	モーションモードのコンテキストを消去。　派生クラスでオーバライドされる。
	     * 
	     * @warning このクラスレベルでこのメソッドが呼ばれた場合、ログエラーを出力。
	     */
	    public	void	EndMotionModeBlock()
	    {
	        logInvalidNesting();
	    }

	    /**
	     * 必ず継承してオーバライドすること。<br>
	     * ModeBlock自体がインスタンス化されるため、abstruct扱いすることができない。
	     */
	    public	CqOptions optCurrent(){
	    	return null;
	    }
	    
	    /**
	     * Get a read only pointer to the current attributes.<br>
	     * 現在のアトリビュートのゲッタ。
	     * 
	     * @return	m_pattrCurrent	現在のアトリビュート
	     */
	    public CqAttributes pattrCurrent()
	    {	
	        return ( m_pattrCurrent );
	    }
	    
	    /** 
	     * Set the current set of attributes<br>
	     * 現在のアトリビュートのセッタ。
	     * 
	     * @param	newattrs	セットするアトリビュート
	     * @return prev　古いアトリビュート
	     */
	    public final CqAttributes pattrCurrent(CqAttributes newattrs)
	    {
	        CqAttributes prev = m_pattrCurrent;
	        m_pattrCurrent = newattrs;
	        return ( prev );
	    }
	    
	    /** 
	     * Get a pointer to the current attributes suitable for writing.<br>
	     * 現在の書く込むアトリビュートのゲッタ。
	     * 
	     * @return 	m_pattrCurrent	現在のアトリビュート
	     */
	    public	CqAttributes pattrWriteCurrent()
	    {
	        m_pattrCurrent = m_pattrCurrent.Write();
	        return ( m_pattrCurrent );
	    }
	    
	    /** 
	     * Get a read only pointer to the current transform.<br>
	     * 現在のトランスフォームノゲッタ。
	     * @return	 m_ptransCurrent	現在のトランスフォーム
	     */
	    public	CqTransform	ptransCurrent()
	    {
	        return ( m_ptransCurrent );
	    }
	    
	    /**
	     * Set the current transform.<br>
	     * 	現在のトランスフォームのセッタ。
	     * 
	     * @param
	     * @return 	prev	古いトランスフォーム
	     */
	    public	CqTransform ptransSetCurrent(final CqTransform NewTrans)
	    {
	        CqTransform prev = m_ptransCurrent;
	        m_ptransCurrent = NewTrans;
	        return ( prev );
	    }
	    
	    
	    /** 
	     * Get the current time, used only within Motion blocks, all other contexts return 0.<br>
	     * 	現在の時間を取得。 書き込み用のモーションブロックでのみ使用される。<br>
	     * 	他の全てのコンテキストでは0が返される。
	     * 
	     * @return 0.0f	フローとの現在の時間が返される。
	     * 
	     */
	    public	float	Time()
	    {
	        return ( 0.0f );
	    }
	    
	    /**
	     * Advance the current frame time to the next specified time.<br>
	     *　	現在のフレーム時間から指定された次の時間を進めてください。
	     */
	    public	void	AdvanceTime(){}
	    
	    
	    /**
	     *  Get the current frame index if in a motion block.<br>
	     * 	現在のフレームインデックスを取得。
	     */
	    public	int	TimeIndex()
	    {
			return( 0 );
		}
	    
	    /**
	     * Is this a motion block, should be overridden per derived class.<br>
	     * 	現在モーションブロックの中にいるかどうかを判定。<br>
	     * 	派生クラス全てにオーバーライドされる。
	     * 
	     * @return false	モーションブロックの内側 or　外側の判定。
	     */
	    public	boolean	fMotionBlock()
	    {
	        return ( false );
	    }

	    /** 
	     * Get a pointer to the previuos context.<br>
	     * 前のコンテキストのゲッタ。
	     * 
	     * @return	m_pconParent	コンテキスト
	     */
	    public CqModeBlock pconParent()
	    {
	        return ( m_pconParent );
	    }

	    /** 
	     * Get the type.<br>
	     * モードタイプのゲッタ。
	     * 
	     * @return m_ModeType	モードタイプ
	     */
	    public EqModeBlock Type()
	    {
	        return ( m_modetype );
	    }
	    
	    
	    /**
	     * Get a reference to the current transformation matrix, <br>
	     *	the result of combining all transformations up to this point.<br>
	     * 	現在の、トランスフォームしたマトリックスを取得。<br>
	     * 	このメソッドが呼び出される時には、すべての変化を結合した結果がでている。
	     * 
	     * @param time
	     * @return	マトリックス
	     */
	    public CqMatrix	matCurrent( float time )
	    {
	        return ( ptransCurrent().matObjectToWorld( time ) );
	    }

	    /**
	     * ライトソースをスタックに追加<br>
	     * CqWorldModeBlockクラス(派生)にのみ、オーバーライドされる。
	     * 
	     * @param pLS ライトソース
	     */
	    public	void	AddContextLightSource( final CqLightsource pLS )
	    {
	        if ( pconParent() != null)
	            pconParent().AddContextLightSource( pLS );
	    }

	    /**
	     * コンテキストがソリッドかどうかを判定。<br>
	     * CqSolidModeBlockクラス(派生)にのみ、オーバーライドされる。
	     * 
	     * @return	true / false 判定
	     */
	    public	boolean	isSolid()
	    {
	        return ( ( pconParent() != null) ? pconParent().isSolid() : false );
	    }
	    
	    /** 
	     * Get a pointer to the CSG tree node related to this context.<br>
	     * 現在のコンテキストに関連するCSG木のノードを取得。<br>
	     * CqSolidModeBlockクラス(派生)にのみ、オーバーライドされる。
	     * 
	     * @return オプション参照
	     */
	    public CqCSGTreeNode pCSGNode()
	    {
	    	return ( ( pconParent()!= null ) ? pconParent().pCSGNode() : null );
	    }

	    /** 
	     * エラーログ表示
	     */
	    public void logInvalidNesting()
	    { 
	    	logger.critical( "Invalid context nesting" );
	    }
	    
	    public CqAttributes m_pattrCurrent ;	//　現在持っているアトリビュート	The current attributes.
	    public CqTransform 	m_ptransCurrent ;	// 現在持っている変換情報	The current transformation
	    
	    private CqModeBlock	m_pconParent;		//　前のコンテキスト	The previous context.
	    private EqModeBlock	m_modetype = new EqModeBlock();	//The current type of motionblock in order to double check the delete				
	    private HimawariLogger logger = HimawariLogger.getLogger();

}
