/// ****************************************************************************
/// @file   
/// @author Dr.Neeton
/// @date   2010/X/X - 2016/12/18
/// 
/// @brief  ツリービューノード
/// 
/// ****************************************************************************

#include "CPL_GUC_TreeView.h"


namespace CPL {
namespace GUC {

//const short4 rt_offs_expand_btn( 2,2, 13,13 );
const float cpl_guc_treeviewnode_offs_x = 20;

enum eCPL_IMGBTN_COLOR_ID
{ kCPL_IMGBTN_COLOR_ID_BLACK
, kCPL_IMGBTN_COLOR_ID_GRAY
, kCPL_IMGBTN_COLOR_ID_RED
, kCPL_IMGBTN_COLOR_ID_BLUE
, kCPL_IMGBTN_COLOR_ID_WHITE
};

enum eCPL_IMGBTN_VIEW_STATE
{ kCPL_IMGBTN_VIEW_STATE_PLUS_DEFAULT
, kCPL_IMGBTN_VIEW_STATE_PLUS_HIGHLIGHT
, kCPL_IMGBTN_VIEW_STATE_MINUS_DEFAULT
, kCPL_IMGBTN_VIEW_STATE_MINUS_HIGHLIGHT
};

// _____________________________________________________________________________
/// @brief コンストラクタ
/// 
/// @copydoc doxycomment::arg_in_sp_component_for_parent
/// @param[in] in_sp_item_comp
///   : 追加するアイテムとなるコンポーネントのスマートポインタを指定します。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
TreeViewNode::TreeViewNode
( _in<sdptr<Component>> in_sp_component_for_parent
, _in<sdptr<Component>> in_sp_item_comp
) : td_base
    ( in_sp_component_for_parent
    , kPOS_DEFAULT
    , kSIZE_DEFAULT
    )
  , m_sp_item_comp( in_sp_item_comp )
  , m_flag_expand( true )
{
  zzz_setFrameSize_( 1 );

  // アイテムを自身の子供にする。
  AddLinkChild( in_sp_item_comp );

  // 展開ボタンの作成
  m_sp_button =
    Factory<ButtonImage>::Create
      ( GetLinkMyself()
      , float2(0,0)
      , float2(16,16)
      , sm_tex_parts()
      , CPL_GUC_DEF_STR("")
      );
  m_sp_button->SetStateVisible( false ); // 最初は非表示に。
  // uvテーブル追加
  int parts_ID[] = {
    eImagePartsID::Circle,
    eImagePartsID::CircleShadow,
    eImagePartsID::Plus,
    eImagePartsID::Minus
  };
  //CPL_LOOP2( CPL_ARRAY_NUM(parts_ID), idx )
  for( int idx = 0; idx < CPL_ARRAY_NUM(parts_ID); ++idx )
  {
    float ID = static_cast<float>(parts_ID[ idx ]);
    m_sp_button->AddRect
      ( static_cast<int>(ID)
      , float4( 0, ID*16, 16, ID*16+16 )
      );
  }
  // カラー設定
  m_sp_button->AddColor( kCPL_IMGBTN_COLOR_ID_BLACK, kCOLOR_BLACK );
  m_sp_button->AddColor( kCPL_IMGBTN_COLOR_ID_GRAY,  kCOLOR_LIGHTGRAY );
  m_sp_button->AddColor( kCPL_IMGBTN_COLOR_ID_RED,   kCOLOR_RED );
  m_sp_button->AddColor( kCPL_IMGBTN_COLOR_ID_BLUE,  CDI::ColorType(0.8f,0.8f,1.0f,1.0f) );
  m_sp_button->AddColor( kCPL_IMGBTN_COLOR_ID_WHITE, kCOLOR_WHITE );
  // 状態設定
  GUC::ButtonImage::LinkIDs lid_plus_default[] = {
    GUC::ButtonImage::LinkIDs( 0, eImagePartsID::Circle,       kCPL_IMGBTN_COLOR_ID_GRAY ),
    GUC::ButtonImage::LinkIDs( 0, eImagePartsID::CircleShadow, kCPL_IMGBTN_COLOR_ID_WHITE ),
    GUC::ButtonImage::LinkIDs( 0, eImagePartsID::Plus,         kCPL_IMGBTN_COLOR_ID_BLACK )
  };
  GUC::ButtonImage::LinkIDs lid_plus_highlight[] = {
    GUC::ButtonImage::LinkIDs( 0, eImagePartsID::Circle,       kCPL_IMGBTN_COLOR_ID_BLUE ),
    GUC::ButtonImage::LinkIDs( 0, eImagePartsID::CircleShadow, kCPL_IMGBTN_COLOR_ID_WHITE ),
    GUC::ButtonImage::LinkIDs( 0, eImagePartsID::Plus,         kCPL_IMGBTN_COLOR_ID_RED )
  };
  GUC::ButtonImage::LinkIDs lid_minus_default[] = {
    GUC::ButtonImage::LinkIDs( 0, eImagePartsID::Circle,       kCPL_IMGBTN_COLOR_ID_GRAY ),
    GUC::ButtonImage::LinkIDs( 0, eImagePartsID::CircleShadow, kCPL_IMGBTN_COLOR_ID_WHITE ),
    GUC::ButtonImage::LinkIDs( 0, eImagePartsID::Minus,        kCPL_IMGBTN_COLOR_ID_BLACK )
  };
  GUC::ButtonImage::LinkIDs lid_minus_highlight[] = {
    GUC::ButtonImage::LinkIDs( 0, eImagePartsID::Circle,       kCPL_IMGBTN_COLOR_ID_BLUE ),
    GUC::ButtonImage::LinkIDs( 0, eImagePartsID::CircleShadow, kCPL_IMGBTN_COLOR_ID_WHITE ),
    GUC::ButtonImage::LinkIDs( 0, eImagePartsID::Minus,        kCPL_IMGBTN_COLOR_ID_RED )
  };
  m_sp_button->AddDrawStateLink
    ( kCPL_IMGBTN_VIEW_STATE_PLUS_DEFAULT
    , lid_plus_default
    , CPL_ARRAY_NUM(lid_plus_default)
    );
  m_sp_button->AddDrawStateLink
    ( kCPL_IMGBTN_VIEW_STATE_PLUS_HIGHLIGHT
    , lid_plus_highlight
    , CPL_ARRAY_NUM(lid_plus_highlight)
    );
  m_sp_button->AddDrawStateLink
    ( kCPL_IMGBTN_VIEW_STATE_MINUS_DEFAULT
    , lid_minus_default
    , CPL_ARRAY_NUM(lid_minus_default)
    );
  m_sp_button->AddDrawStateLink
    ( kCPL_IMGBTN_VIEW_STATE_MINUS_HIGHLIGHT
    , lid_minus_highlight
    , CPL_ARRAY_NUM(lid_minus_highlight)
    );
  //
  //m_sp_button->SetDrawStateID( kCPL_IMGBTN_VIEW_STATE_PLUS_DEFAULT );
  //
  m_sp_button->SetAutoChangeImageState
    ( kCPL_IMGBTN_VIEW_STATE_PLUS_DEFAULT
    , kCPL_IMGBTN_VIEW_STATE_PLUS_HIGHLIGHT
    , -1
    , -1
    );

  zzf_setupDrawState( false, false, false ); // 描画ステートのデフォルト設定。
  // 初期化済みフラグ設定
  zzf_SetInitializedLevel( zzf_GetClassLevel() );

  if( m_sp_item_comp )
  {
    // 位置・サイズの設定
    m_sp_item_comp->SetPosition
      ( float2{ cpl_guc_treeviewnode_offs_x, 0 }
      );
    m_sp_item_comp->SetBelongComponent
      ( GetLinkMyself()
      , eParentType::Position
      );
    SetSize
      ( m_sp_item_comp->GetSize()
        + float2{ cpl_guc_treeviewnode_offs_x, 0 }
      );
  }
}


// _____________________________________________________________________________
/// @brief コピーコンストラクタ
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
TreeViewNode::TreeViewNode( cref<TreeViewNode> in_TVI )
  : td_base( in_TVI )
  , m_sp_button
    { FindComponentT_by_UserID<ButtonImage>( in_TVI.m_sp_button )
    }
  , m_sp_item_comp
    { FindComponentT_by_UserID<Component>( in_TVI.m_sp_item_comp )
    }
  , m_flag_expand( in_TVI.m_flag_expand )
{
  m_sp_button   ->SetAutoUserID();
  m_sp_item_comp->SetAutoUserID();
}


// _____________________________________________________________________________
/// @brief デストラクタ
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
TreeViewNode::~TreeViewNode()
{
}


// _____________________________________________________________________________
/// @copydoc CPL::GUC::Component::CreateClone
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sdptr<Component>
  TreeViewNode::CreateClone
    ( _in<sdptr<Component>> in_sp_component_for_parent
    , _in<float2          > in_offset_position_from_original
    ) const
{
  return
    zzz_CreateClone_Basic<td_self>
      ( in_sp_component_for_parent
      , in_offset_position_from_original
      );
}


// _____________________________________________________________________________
/// @brief 前方のツリービューノードの取得
/// 
/// ※ アイテムが子供として登録される都合上、アイテムをツリービューノードとして
///    扱わないよう、独自に処理をします。
/// 
/// @return 自身の１つ前のツリービューノードを指すスマートポインタを返します。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sdptr<TreeViewNode> TreeViewNode::GetLinkPrevTVN() const
{
  auto sp_comp_prev = GetLinkPrev();

  while( sp_comp_prev )
  {
    if( auto sp_tvi = std::dynamic_pointer_cast<TreeViewNode>( sp_comp_prev ) )
    {
      return sp_tvi;
    }
    sp_comp_prev = sp_comp_prev->GetLinkPrev();
  }

  return nullptr;
}

// _____________________________________________________________________________
/// @brief 後方のツリービューノードを取得
/// 
/// ※ アイテムが子供として登録される都合上、アイテムをツリービューノードとして
///    扱わないよう、独自に処理をします。
/// 
/// @return 自身の１つ後ろのツリービューノードを指すスマートポインタを返します。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sdptr<TreeViewNode> TreeViewNode::GetLinkNextTVN() const
{
  auto sp_comp_next = GetLinkNext();

  while( sp_comp_next )
  {
    if( auto sp_tvi = std::dynamic_pointer_cast<TreeViewNode>(sp_comp_next) )
    {
      return std::dynamic_pointer_cast<TreeViewNode>(sp_comp_next);
    }
    sp_comp_next = sp_comp_next->GetLinkNext();
  }

  return nullptr;
}


// _____________________________________________________________________________
/// @brief 親ノードの取得
/// 
/// @return 親のツリービューノードを指すスマートポインタを返します。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sdptr<TreeViewNode> TreeViewNode::GetLinkParentTVN() const
{
  return std::dynamic_pointer_cast<TreeViewNode>(GetLinkParent());
}


// _____________________________________________________________________________
/// @brief 子供ノードの取得
/// 
/// ※ アイテムが子供として登録される都合上、子供を取得する場合は、
///    アイテム（子供）の次の要素を返すようにします。
/// 
/// @return 自身の子供のツリービューノードを指すスマートポインタを返します。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sdptr<TreeViewNode> TreeViewNode::GetLinkChildTVN() const
{
  auto sp_comp_child = GetLinkChild();

  while( sp_comp_child )
  {
    if( auto sp_tvi = std::dynamic_pointer_cast<TreeViewNode>(sp_comp_child) )
    {
      return sp_tvi;
    }
    sp_comp_child = sp_comp_child->GetLinkNext();
  }

  return nullptr;
}

// _____________________________________________________________________________
/// @brief ツリービューノード全体での次のノードを取得
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sdptr<TreeViewNode> TreeViewNode::GetLinkNextAllTVN() const
{
  if( auto sp_comp_child = GetLinkChildTVN() )
  {
    return sp_comp_child;
  }
  if( auto sp_comp_next = GetLinkNextTVN() )
  {
    return sp_comp_next;
  }
  auto sp_comp_parent = GetLinkParentTVN();
  while( sp_comp_parent )
  {
    if( auto sp_comp_parent_next = sp_comp_parent->GetLinkNextTVN() )
    {
      return sp_comp_parent_next;
    }
    sp_comp_parent = GetLinkParentTVN();
  }
  return nullptr;
}


// _____________________________________________________________________________
/// @brief 子アイテムが全て含まれるのに必要なサイズの取得
/// 
/// @param[in] in_flag_show
///   : 表示状態フラグ。\n
///   : true  - 非表示コンポーネントも含めて計算します。
///   : false - 表示コンポーネントのみで計算します。
/// 
/// @return 計算されたサイズをfloat2型で返します。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
float2 TreeViewNode::GetAdjustSize( _in<BOOL> in_flag_show ) const noexcept
{
  if( auto sp_item_comp = m_sp_item_comp )
  {
    float2 size = sp_item_comp->GetAdjustSize( in_flag_show );
    size += sp_item_comp->GetPosition();

    return size;
  }
  else
  {
    return float2( 40, GetLineHeight() );
  }
}


// _____________________________________________________________________________
/// @copydoc CPL::GUC::Component::On_MouseDown
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
eEventReturnID
  TreeViewNode::On_MouseDown
    ( _in<sdptr<Component>> in_sp_component
    , _in<float           > in_mouse_x
    , _in<float           > in_mouse_y
    , _in<eMouseButton    > in_type_mouse_btn
    )
{
  if( in_sp_component == GetLinkMyself() )
  {
    ActivateTopOrder();
  }

  if( in_sp_component == m_sp_button )
  {
    m_flag_expand = !m_flag_expand;

    if( m_flag_expand )
    {
      m_sp_button->SetAutoChangeImageState
        ( kCPL_IMGBTN_VIEW_STATE_PLUS_DEFAULT
        , kCPL_IMGBTN_VIEW_STATE_PLUS_HIGHLIGHT
        , -1
        , -1
        );
      //m_sp_button->SetDrawStateID( kCPL_IMGBTN_VIEW_STATE_PLUS_HIGHLIGHT );
    }
    else
    {
      m_sp_button->SetAutoChangeImageState
        ( kCPL_IMGBTN_VIEW_STATE_MINUS_DEFAULT
        , kCPL_IMGBTN_VIEW_STATE_MINUS_HIGHLIGHT
        , -1
        , -1
        );
      //m_sp_button->SetDrawStateID( kCPL_IMGBTN_VIEW_STATE_MINUS_HIGHLIGHT );
    }

    //if( GetBelongComponent() )
    //{
    //  GetBelongComponent()->call_On_MouseDown(
    //    GetLinkMyself(), in_mouse_x, in_mouse_y, in_type_mouse_btn );
    //}
    m_sp_button->Update();
  }

  return eEventReturnID::SendParent_Position;
}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// クライアント描画
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//void TreeViewNode::On_DrawClient( short4 in_rect )
//{
//  short4 rt = m_sp_button->GetRectCoord();
//  const short btn_w  = rt.Width();
//  const short btn_h  = rt.Height();
//  const short btn_cx = rt.left + btn_w / 2 + 1;
//  const short btn_cy = rt.top  + btn_h / 2 + 1;
//  const short btn_w2 = btn_w / 2;
//  const short btn_h2 = btn_h / 2;
//  // vtx
//  DrawVtxInfo vtx[2] = {
//    DrawVtxInfo( 0.0f, 0.0f, 0.0f, COLOr_BLACK ),
//    DrawVtxInfo( 0.0f, 0.0f, 0.0f, COLOr_BLACK ),
//  };
/*
  // draw this line
  vtx[0].x = static_cast<float>(in_rect.x + btn_cx);
  vtx[0].y = static_cast<float>(in_rect.y + btn_cy);
  vtx[1].x = static_cast<float>(in_rect.x + cpl_guc_treeviewnode_offs_x);
  vtx[1].y = static_cast<float>(in_rect.y + btn_cy);
  zzf_DrawPolygon( vtx, 2, D3D11_PRIMITIVE_TOPOLOGY_LINELIST );

  // draw prev line
  if( GetNodeParent()  &&  GetNodePrev() )
  {
    if( GetNodeParent().GetNodeChild() != GetItemComponent() )
    {
      vtx[0].x = static_cast<float>(in_rect.x + btn_cx);
      vtx[0].y = static_cast<float>(in_rect.y + btn_cy);
      vtx[1].x = static_cast<float>(in_rect.x + btn_cx);
      vtx[1].y = static_cast<float>(in_rect.y + 2);
      zzf_DrawPolygon( vtx, 2, D3D11_PRIMITIVE_TOPOLOGY_LINELIST );
    }
  }

  // draw next line
  if( GetNodeNext() )
  {
    vtx[0].x = static_cast<float>(in_rect.x + btn_cx);
    vtx[0].y = static_cast<float>(in_rect.y + btn_cy);
    vtx[1].x = static_cast<float>(in_rect.x + btn_cx);
    vtx[1].y = in_rect.w + ;
    zzf_DrawPolygon( vtx, 2, D3D11_PRIMITIVE_TOPOLOGY_LINELIST );
  }*/

/*  // draw +/-
  if( GetNodeChild() )
  {

      short4 rt = sp_tv_node->GetRectCoord();
      MappingPosition( sp_tv_node.GetNodeParent(), GetLinkMyself(), (short2_ptr)&rt, 2 );
      rt.x += rt_offs_expand_btn.x;
      rt.y += rt_offs_expand_btn.y;
      rt.z = rt.x + rt_offs_expand_btn.Width();
      rt.w = rt.y + rt_offs_expand_btn.Height();

      if( rt.IsHit( in_mouse_x, in_mouse_y ) )
      {
        ここから↑
      }



    short4 rt( in_rect.x + btn_x0,
               in_rect.y + btn_y0,
               in_rect.x + btn_x1,
               in_rect.y + btn_y1 );
//    // box
//    zzf_DrawRect( rt, COLOr_WHITE );
    CDI::ColorType color_circle = COLOr_GRAY;
    CDI::ColorType color_mark   = COLOr_WHITE;
    if( sm_sp_ac_comp() == this )
    {
      color_circle = CDI::ColorType(0.8f,0.8f,1.0f,1.0f);
      color_mark   = COLOr_BLACK;
    }
    // circle
    zzf_DrawParts(
      short2(rt.x-3, rt.y-3),
      eImagePartsID::Circle,
      color_circle );
    zzf_DrawParts(
      short2(rt.x-3, rt.y-3),
      eImagePartsID::CircleShadow,
      COLOr_WHITE );

    if( GetFlag_Expand() )
    {
      zzf_DrawParts(
        short2(rt.x-3, rt.y-3),
        eImagePartsID::Minus,
        color_mark );
    }
    else
    { 
      zzf_DrawParts(
        short2(rt.x-3, rt.y-3),
        eImagePartsID::Plus,
        color_mark );
    }
  }*/

//}




} // namespace GUC
} // namespace CPL

