/// ****************************************************************************
/// @file   
/// @author Dr.Neeton
/// @date   200X/X/X - 2015/11/14
/// 
/// @brief  DirectX シェーダーコードフラグメント用変数定義クラス関連。
/// 
/// ****************************************************************************

#pragma once

#include "CPL_DX_Shader_CodeItemVariable.h"

namespace CPL {
namespace DX {
namespace Shader {


// _____________________________________________________________________________
/// @brief シェーダーコード構造体定義フラグメントクラス
/// 
/// 関数構文
/** @verbatim
[StorageClass] [precise] Return_Value Name ( [ArgumentList] ) [: Semantic] 
{ 
  [StatementBlock] 
};
@endverbatim*/
///
// *****************************************************************************
class CodeItemFunction
  : public CodeItem
{
  friend class CodeItemFunction;
protected:
  css16       m_strage_class;
  css128      m_type;
  css128      m_function_name;
  CodeItemSet m_item_set; // 引数リスト
  css32       m_semantic;
  ss          m_statement_block; // 実装部分の文字列

  bool zzf_SetParameter( Parameter_ const& in_param );
public:
  CodeItemFunction();
  CodeItemFunction( cref<CodeItemFunction> in_cif );
  CodeItemFunction( _in<Parameter_> in_param );
  virtual ~CodeItemFunction();
  
  char_cptr GetStrageClass()    const { return m_strage_class; }
  char_cptr GetTypeModifier()   const { return ""; }
  char_cptr GetInputModifier()  const { return ""; }
  char_cptr GetType()           const { return m_type; }
  char_cptr GetName()           const { return m_function_name; }
  char_cptr GetSemantic()       const { return m_semantic; }
  char_cptr GetAnnotation()     const { return ""; }
  char_cptr GetInitilize()      const { return ""; }
  char_cptr GetPackOffset()     const { return ""; }
  char_cptr GetRegister()       const { return ""; }
  char_cptr GetStatementBlock() const { return m_statement_block; }
  char_cptr GetInterpolation()  const { return ""; }
  int       GetNum()            const { return 0; }

  // _____________________________________________________________________________
  /// @brief 保持アイテム数の取得
  /// 
  /// @return 保持アイテム数を返します。
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  size_t GetItemNum() const
  {
    return m_item_set.GetItemNum();
  }

  // _____________________________________________________________________________
  /// @brief 保持アイテムの取得
  /// 
  /// @param[in] in_index : 取得したいアイテムのインデックスを指定します。
  /// 
  /// @return 該当するアイテムを指すスマートポインタを返します。
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  sdptr<CodeItem>
    GetItem( _in<size_t> in_index ) const
  {
    return m_item_set.GetItem( in_index );
  }

  // _____________________________________________________________________________
  /// @brief 型を指定したアイテムの取得
  /// 
  /// @param[in] in_offs_idx
  ///   : 取得したいアイテムのインデックスを指定します。\n
  ///   : インデックスは指定した型のみ対象としたインデックスになります。
  /// 
  /// @return 該当するアイテムを指すスマートポインタを返します。
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  template<class T_Item>
  sdptr<T_Item>
    FindItem( size_t in_offs_idx = 0 ) const
  {
    return m_item_set.FindItem<T_Item>( in_offs_idx );
  }

  // _____________________________________________________________________________
  /// @copydoc CodeItemSet::FindItem(cref<Parameter_>,cref<Parameter_>,cref<Parameter_>)const
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  template<class T_Item>
  std::shared_ptr<T_Item>
    FindItem
      ( _in<Parameter_> in_param0
      , _in<Parameter_> in_param1 = NonParam_("")
      , _in<Parameter_> in_param2 = NonParam_("")
      ) const
  {
    return m_item_set.FindItem<T_Item>( in_param0, in_param1, in_param2 );
  }

  // _____________________________________________________________________________
  /// @brief アイテムの登録
  /// 
  /// @param[in] in_item : 登録するコードアイテムを指定します。
  /// 
  /// @retval true  : 登録成功。
  /// @retval false : 登録失敗。
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  template<class T_Item>
  bool Entry( cref<T_Item> in_item )
  {
    return m_item_set.Entry( in_item );
  }

  // _____________________________________________________________________________
  /// @brief 代入
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  CodeItemFunction& operator =  ( cref<CodeItemFunction> in_item );

  CodeItemFunction& operator =  ( _in<StrageClass   > in_strage_class    ){ m_strage_class   .Reset( in_strage_class    ); return *this; } // パラメーター設定
  CodeItemFunction& operator =  ( _in<Type          > in_type            ){ m_type           .Reset( in_type            ); return *this; } // パラメーター設定
  CodeItemFunction& operator =  ( _in<Name          > in_function_name   ){ m_function_name  .Reset( in_function_name   ); return *this; } // パラメーター設定
  CodeItemFunction& operator =  ( _in<Semantic      > in_semantic        ){ m_semantic       .Reset( in_semantic        ); return *this; } // パラメーター設定
  CodeItemFunction& operator =  ( _in<StatementBlock> in_statement_block ){ m_statement_block.Reset( in_statement_block ); return *this; } // パラメーター設定

  
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // アイテム登録
  template<class T_Item>
  CodeItemFunction& operator << ( cref<T_Item> in_item )
  {
    Entry( in_item );
    return *this;
  }
  CodeItemFunction& operator << ( _in<StrageClass   > in_strage_class    ){ return (*this) = in_strage_class   ; } // パラメーター設定
  CodeItemFunction& operator << ( _in<Type          > in_type            ){ return (*this) = in_type           ; } // パラメーター設定
  CodeItemFunction& operator << ( _in<Name          > in_function_name   ){ return (*this) = in_function_name  ; } // パラメーター設定
  CodeItemFunction& operator << ( _in<Semantic      > in_semantic        ){ return (*this) = in_semantic       ; } // パラメーター設定
  CodeItemFunction& operator << ( _in<StatementBlock> in_statement_block ){ return (*this) = in_statement_block; } // パラメーター設定

  bool operator == ( cref<CodeItem> in_item ) const;
  bool operator != ( cref<CodeItem> in_item ) const
  {
    return !((*this) == in_item);
  }

  void MakeCode( rout<ss> out_buf, _in<eCreateType> in_create_type ) const;
};

typedef CodeItemFunction CIFunction;


} // namespace Shader
} // namespace DX
} // namesapace CPL
