/// ****************************************************************************
/// @file   
/// @author Dr.Neeton
/// @date   200X/X/X - 2014/01/24
/// 
/// @brief  DirectX ピクセルシェーダ関連。
/// 
/// ****************************************************************************

#pragma once

//#include "CPL_DX_CommonShaderFragment.h"
#include "CPL_DX_Shader_VS_Fragment.h"


namespace CPL {
namespace DX {
namespace Shader {
namespace PSF {

  //***** 頂点シェーダーと共通フラグメントの再定義 *****//

  // 入力カラー
  typedef VSF::Input_Color Input_Color;
  CPL_DX_CSF_DEFINED_DERIVED_CLASS_N_TYPE( Input_Color );

  // 入力テクスチャ座標
  typedef VSF::Input_TexCoord Input_TexCoord;
  CPL_DX_CSF_DEFINED_DERIVED_CLASS_N_TYPE( Input_TexCoord );


  // =============================================================================
  // 入力パラメーター：カラー（ターゲット）
  // =============================================================================
  //class Input_SV_Target :
  //  virtual public CodeFragment,
  //  public CSF::KW_InTarget
  //{
  //protected:
  //  int m_in_target;

  //  void On_SetupInputParameter( rout<CIV_Input> out_input_param ) override;

  //  CPL_DEF_GET_THIS_FRAGMENT_COLLECTION
  //public:
  //  Input_SV_Target( int No = 0 ) :
  //    m_in_target( No )
  //  {}
  //  ~Input_SV_Target(){}
  //};


  // _____________________________________________________________________________
  /// @brief 入力パラメーター：ピクセル座標？
  ///
  // *****************************************************************************
  class Input_SV_Position
    : virtual public CodeFragment
    , public CSF::KW_InSV_Position
  {
  protected:
    int m_in_vpos;

    void On_SetupInputParameter( rout<CIV_Input> out_input_param ) override;

    CPL_DEF_GET_THIS_FRAGMENT_COLLECTION
  public:
    Input_SV_Position( int No = 0 )
      : m_in_vpos( No )
    {}
    ~Input_SV_Position(){}
  };


  // _____________________________________________________________________________
  /// @brief 入力パラメーター：プリミティブの方向
  ///
  // *****************************************************************************
  class Input_VFace
    : virtual public CodeFragment
    , public CSF::KW_InVFace
  {
  protected:
    int m_in_vface;

    void On_SetupInputParameter( rout<CIV_Input> out_input_param ) override;

    CPL_DEF_GET_THIS_FRAGMENT_COLLECTION
  public:
    Input_VFace( int No = 0 )
      : m_in_vface( No )
    {}
    ~Input_VFace(){}
  };


  // _____________________________________________________________________________
  /// @brief 出力パラメーター：カラー？
  ///
  // *****************************************************************************
  class Output_Target
    : virtual public CodeFragment
    , public CSF::KW_OutTarget
  {
  protected:
    int m_target_No;
    
    void On_SetupOutputParameter( rout<CIV_Output> out_output_param ) override;

    CPL_DEF_GET_THIS_FRAGMENT_COLLECTION
  public:
    Output_Target( int No = 0 )
      : m_target_No( No )
    {}
  };

  // _____________________________________________________________________________
  /// @brief 出力パラメーター：深度
  ///
  // *****************************************************************************
  class Output_Depth
    : virtual public CodeFragment
    , public CSF::KW_OutDepth
  {
  protected:
    int m_depth_No;

    void On_SetupOutputParameter( rout<CIV_Output> out_output_param ) override;

    CPL_DEF_GET_THIS_FRAGMENT_COLLECTION
  public:
    Output_Depth( int No = 0 ) : m_depth_No( No ){}
    ~Output_Depth(){}
  };

  CPL_DX_CSF_DEFINED_DERIVED_CLASS_N_TYPE( Output_Depth );

  

  // _____________________________________________________________________________
  /// @brief テクスチャコード
  ///
  // *****************************************************************************
  class Texture
    : public CSF::Global_Texture2D
    , public CSF::Global_SamplerState
    , public CSF::Global_Material // マテリアルカラーモード時のみ使用する。
    , public Input_Color // 頂点カラーモード時のみ使用する。
    , public Input_TexCoord
    , public Output_Target
  {
  protected:
    int m_stage_num;
    int m_color_type;
    
    void On_SetupGlobalParameter( rout<CIV_Global> out_global_param ) override;
    void On_SetupInputParameter ( rout<CIV_Input> out_input_param ) override;
    void On_SetupOutputParameter( rout<CIV_Output> out_output_param ) override;
    void On_SetupFunction
          ( rout<CIFunctionSet> out_functions
          , _in <CIV_Global   > in_global_param
          ) override;
    void On_CallFunction( rout<ss> out_statement, _in<CodeItemSet> in_parameter ) override;
    void On_SetupInitializer( rout<CIV_Initializer> out_initialize_param ) override;
    //void On_SetupFinalizer( CIV_Finalizer& out_finalize_param );

    CPL_DEF_GET_THIS_FRAGMENT_COLLECTION
    char_cptr zzf_getFunctionName() const { return "TextureFunc"; }
  public:
    Texture( int in_stage_num )
      : Global_Texture2D( 1 )
      , Global_SamplerState( in_stage_num )
      , m_stage_num( in_stage_num )
      , m_color_type( 0 )
    {}
    ~Texture(){}
  };

  // _____________________________________________________________________________
  /// @brief カラーセット
  ///
  // *****************************************************************************
  class SetColor
    : public CSF::Global_PixelColor
    , public Output_Target
  {
  protected:
    float4 m_color;
    
    void On_SetupGlobalParameter( rout<CIV_Global> out_global_param ) override;
    void On_SetupOutputParameter( rout<CIV_Output> out_output_param ) override;
    void On_CallFunction( rout<ss> out_statement, _in<CodeItemSet> in_parameter ) override;

    CPL_DEF_GET_THIS_FRAGMENT_COLLECTION
    //char_cptr zzf_getFunctionName() const { return "SetColor"; }
  public:
    //static css vn_g_pixel_color()
    //{
    //  static css color("vn_g_pixel_color");
    //  return color;
    //}

    SetColor() : m_color( 1.0f, 1.0f, 1.0f, 0 ) {}
    SetColor( float4_cref in_color ) : m_color(in_color) {}
    SetColor( float a, float r, float g, float b ) : m_color( a,r,g,b ) {}
    ~SetColor(){}
  };



  // _____________________________________________________________________________
  /// @brief アンビエントライトコード
  ///
  // *****************************************************************************
  class AmbientLight
    : public CSF::zzz_::BaseLight
    , public Input_Color // Input_Colorは頂点カラー時のみ処理する。
    , public Output_Target
    , public CSF::KW_G_Material
    , public CSF::KW_G_AmbientLight
    , public CSF::KW_Diffuse
  {
  protected:
    void On_SetupGlobalParameter( rout<CIV_Global> out_global_param ) override;
    void On_SetupInputParameter( rout<CIV_Input> out_input_param ) override;
    void On_SetupOutputParameter( rout<CIV_Output> out_output_param ) override;
    void On_SetupFunction( rout<CIFunctionSet> out_functions, _in<CIV_Global> in_global_param ) override;
    void On_CallFunction( rout<ss> out_statement, _in<CodeItemSet> in_parameter ) override;
    void On_SetupInitializer( rout<CIV_Initializer> out_initialize_param ) override;

    CPL_DEF_GET_THIS_FRAGMENT_COLLECTION

    //U32 m_color_type; // 0:vertex color  1:material color
  public:
    //AmbientLight( U32 in_color_type ) : m_color_type(in_color_type) {}
    AmbientLight() : BaseLight( 1 ) {}
    ~AmbientLight(){}
  };

  
  // _____________________________________________________________________________
  /// @brief ディレクショナルライトコード
  ///
  // *****************************************************************************
  class DirectionalLight
    : public CSF::zzz_::BaseLight
    , public Output_Target
    , public CSF::KW_G_DirectionalLight
    , public CSF::KW_G_Material
    , public CSF::KW_Diffuse
    , public CSF::KW_Specular
    , public CSF::KW_Normal
    , public CSF::KW_Power
    , public CSF::KW_InPosition
    , public CSF::KW_InNormal
    , public CSF::KW_InColor // 頂点カラーモードのみ使用する
  {
  protected:
    void On_SetupGlobalParameter( rout<CIV_Global> out_global_param ) override;
    void On_SetupInputParameter( rout<CIV_Input> out_input_param ) override;
    void On_SetupOutputParameter( rout<CIV_Output> out_output_param ) override;
    void On_SetupFunction( rout<CIFunctionSet> out_functions, _in<CIV_Global> in_global_param ) override;
    void On_CallFunction( rout<ss> out_statement, _in<CodeItemSet> in_parameter ) override;

    CPL_DEF_GET_THIS_FRAGMENT_COLLECTION
  public:
    DirectionalLight( U32 in_light_num )
      : BaseLight( in_light_num ) {}
    ~DirectionalLight(){}
  };

  // _____________________________________________________________________________
  /// @brief ポイントライトコード
  ///
  // *****************************************************************************
  class PointLight
    : public CSF::zzz_::BaseLight
    , public CSF::KW_G_PointLight
    , public CSF::KW_G_Material
    , public CSF::KW_Diffuse
    , public CSF::KW_Position
    , public CSF::KW_Normal
    , public CSF::KW_Power
    , public CSF::KW_InPosition
    , public CSF::KW_InNormal
    , public CSF::KW_InColor // 頂点カラーモードのみ使用する
    , public Output_Target
  {
  protected:
    void On_SetupGlobalParameter( rout<CIV_Global> out_global_param ) override;
    void On_SetupInputParameter( rout<CIV_Input> out_input_param ) override;
    void On_SetupOutputParameter( rout<CIV_Output> out_output_param ) override;
    //void On_SetupInitializer( rout<CIV_Initializer> out_initialize_param ) override;
    void On_SetupFunction( rout<CIFunctionSet> out_functions, _in<CIV_Global> in_global_param ) override;
    void On_CallFunction( rout<ss> out_statement, _in<CodeItemSet> in_parameter ) override;

    CPL_DEF_GET_THIS_FRAGMENT_COLLECTION
  public:
    PointLight( U32 in_light_num )
      : BaseLight( in_light_num ) {}
    ~PointLight(){}
  };
  
  // _____________________________________________________________________________
  /// @brief スポットライトコード
  ///
  // *****************************************************************************
  class SpotLight
    : public CSF::zzz_::BaseLight
    , public CSF::KW_G_SpotLight
    , public CSF::KW_G_Material
    , public CSF::KW_Diffuse
    , public CSF::KW_Specular
    , public CSF::KW_Position
    , public CSF::KW_Normal
    , public CSF::KW_Power
    , public CSF::KW_Theta
    , public CSF::KW_Phi
    , public CSF::KW_InColor // 頂点カラーモードのみ使用する
    , public Output_Target
    , public CSF::KW_InPosition
    , public CSF::KW_InNormal
  {
  protected:
    void On_SetupGlobalParameter( rout<CIV_Global> out_global_param ) override;
    void On_SetupInputParameter( rout<CIV_Input> out_input_param ) override;
    void On_SetupOutputParameter( rout<CIV_Output> out_output_param ) override;
    //void On_SetupInitializer( rout<CIV_Initializer> out_initialize_param ) override;
    void On_SetupFunction( rout<CIFunctionSet> out_functions, _in<CIV_Global> in_global_param ) override;
    void On_CallFunction( rout<ss> out_statement, _in<CodeItemSet> in_parameter ) override;

    CPL_DEF_GET_THIS_FRAGMENT_COLLECTION
  public:
    SpotLight( U32 in_light_num )
      : BaseLight( in_light_num ) {}
    ~SpotLight(){}
  };


  // _____________________________________________________________________________
  /// @brief 頂点カラーをそのまま用いる。
  ///
  // *****************************************************************************
  class ImmediateInputColor
    : public Input_Color
    , public Output_Target
  {
  protected:
    void On_SetupInputParameter( rout<CIV_Input> out_input_param ) override;
    void On_SetupOutputParameter( rout<CIV_Output> out_output_param ) override;
    void On_CallFunction( rout<ss> out_statement, _in<CodeItemSet> in_parameter ) override;

    CPL_DEF_GET_THIS_FRAGMENT_COLLECTION
  public:
    ImmediateInputColor() {}
    ~ImmediateInputColor(){}
  };

  // _____________________________________________________________________________
  /// @brief マテリアルカラーをそのまま用いる。
  ///
  // *****************************************************************************
  class DirectMaterialColor
    : public CSF::Global_Material
    , public Output_Target
  {
  protected:
    void On_SetupGlobalParameter( rout<CIV_Global> out_global_param ) override;
    void On_SetupOutputParameter( rout<CIV_Output> out_output_param ) override;
    void On_CallFunction( rout<ss> out_statement, _in<CodeItemSet> in_parameter ) override;

    CPL_DEF_GET_THIS_FRAGMENT_COLLECTION
  public:
    DirectMaterialColor(){}
    ~DirectMaterialColor(){}
  };




} // namespace PSF
} // namespace Shader
} // namespace DX
} // namespace CPL
