/// ****************************************************************************
/// @file   
/// @author Dr.Neeton
/// @date   2010/X/X - 2017/02/01
/// 
/// @brief  コンテナコンポーネント。
/// 
/// ****************************************************************************

#include "CPL_GUC_Container.h"
#include "CPL_GUC_Layer.h"

namespace CPL {
namespace GUC {


// _____________________________________________________________________________
/// @brief コンストラクタ（ルートレイヤー用）
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Container::Container
( _in<WIN::Component*> in_ptr_win_subject
, _in<float2         > in_position_for_component
, _in<float2         > in_size_for_component
) : Component
    ( in_ptr_win_subject
    , in_position_for_component
    , in_size_for_component
    )
{
  zzz_setFrameSize_( 2 );
  zzf_setupDrawState( false, false, false );
  zzf_SetInitializedLevel( zzf_GetClassLevel() );
}


// _____________________________________________________________________________
/// @brief コンストラクタ（アイテムウィンドウ作成）
/// 
/// @copydetails CPL::GUC::Component::Component(_in<sdptr<Component>>,_in<float2>,_in<float2>)
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Container::Container
( _in<sdptr<Component>> in_sp_component_for_parent
, _in<float2          > in_position_for_component
, _in<float2          > in_size_for_component
) : Component
    ( in_sp_component_for_parent
    , in_position_for_component
    , in_size_for_component
    )
{
  zzz_setFrameSize_( 2 );
  zzf_setupDrawState( false, false, false );
  zzf_SetInitializedLevel( zzf_GetClassLevel() );
}


// _____________________________________________________________________________
/// @brief コピーコンストラクタ
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Container::Container( cref<Container> in_container )
  : Component( in_container )
{
  in_container.zzz_PasteCloneLink( GetLinkMyself() );
}


// _____________________________________________________________________________
/// @brief 子アイテムが全て含まれるのに必要なサイズを取得。
/// 
/// @param[in] in_flag_show
///   : 子アイテムの表示状態による動作を決めます。\n
///   : true  - 非表示コンポーネントも含めてサイズを計算します。\n
///   : false - 非表示コンポーネントは含めずにサイズを計算します。
/// 
/// @return 計算されたサイズを返します。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
float2 Container::GetAdjustSize( _in<BOOL> in_flag_show ) const noexcept
{
  auto const size_frame = GetFrameSize() * IsDrawFrame();
  auto sp_comp = GetLinkChild();
  float2 size( sp_comp ? float2(size_frame) : GetSize() );

  while( sp_comp )
  {
    if( !in_flag_show  ||  sp_comp->IsVisible() )
    {
//      short2 child_adj_size = sp_comp->GetAdjustSize( in_flag_show );
//      size.x = Max<short>( size.x, child_adj_size.x );
//      size.y = Max<short>( size.y, child_adj_size.y );

      //short4 child_adj_rect = sp_comp->GetRectCoord();
      //auto size_child_adj = sp_comp->GetAdjustSize( in_flag_show );// ←これだと、孫やひ孫全て再計算されてしまう。
      auto size_child = sp_comp->GetSize();
      auto pos_child  = sp_comp->GetPosition();

      if( dynamic_cast<GUC::Layer const*>(sp_comp.get()) )
      {
        size_child = sp_comp->GetAdjustSize( in_flag_show );
      }

      size.x = Max<float>( size.x, pos_child.x + size_child.x + size_frame );
      size.y = Max<float>( size.y, pos_child.y + size_child.y + size_frame );
    }

    sp_comp = sp_comp->GetLinkNext();
  }

  return size;
}


// _____________________________________________________________________________
/// @copydoc CPL::GUC::Component::CreateClone
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sdptr<Component>
  Container::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
      );
}

//// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//// コンテナサイズの自動調整
//// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//bool Container::AdjustSize( _in<short2> in_offs_size, _in<BOOL> in_flag_show )
//{
//  short2 adj_size = GetAdjustSize( in_flag_show ) + in_offs_size;
//
//  return SetSize( adj_size );
//}


// _____________________________________________________________________________
/// @copydoc Component::On_Paint
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
float2
  Container::On_Paint
    ( _in<sdptr<Component>> in_sp_draw_owner
    , _in<float2          > in_offset_position_from_parent
    )
{
  auto offs_new =
    Component::On_Paint( in_sp_draw_owner, in_offset_position_from_parent );

  // 子供コンポーネントの描画
  zzf_CallChildPaint( in_sp_draw_owner, offs_new );

  return offs_new;
}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 子供コンポーネントの描画呼び出し
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void
  Container::zzf_CallChildPaint
    ( _in<sdptr<Component>> in_sp_draw_owner
    , _in<float2          > in_pos_offs
    )
{
  sdptr<Component> sp_comp_child = GetLinkChild();
  auto const sp_comp_parent = GetLinkParent();
  auto const sp_comp_owner  = in_sp_draw_owner ? in_sp_draw_owner : GetLinkMyself();
  auto       size_clip = sp_comp_owner->GetSize();
  float4     rt_clip{ 0, 0, size_clip.x, size_clip.y };
  bool const is_clip_owner = sp_comp_owner->IsClipChild();
  if( sp_comp_parent == GetBelongComponent( eParentType::Position ) )
  {
    rt_clip.x -= in_pos_offs.x;
    rt_clip.y -= in_pos_offs.y;
    rt_clip.z -= in_pos_offs.x;
    rt_clip.w -= in_pos_offs.y;
  }
  else
  {
    MappingPosition
      ( sp_comp_owner
      , GetLinkMyself()
      , reinterpret_cast<float2*>(&rt_clip)
      , 2
      );
  }

  while( sp_comp_child )
  {
    if( sp_comp_child->IsVisible() )
    {
      auto rt_child = sp_comp_child->GetRectCoord();
      bool is_clip =
        is_clip_owner  &&
        (typeid(*sp_comp_child) != typeid(Layer))  &&
        (rt_clip.right < rt_child.left  ||  rt_child.right < rt_clip.left  ||
         rt_clip.bottom < rt_child.top  ||  rt_child.bottom < rt_clip.top);
      if( !is_clip )
      {
        sp_comp_child->On_Paint
          ( in_sp_draw_owner
          , in_pos_offs
          );
      }
      else
      {
        int bk = true;
      }
    }

    sp_comp_child = sp_comp_child->GetLinkNext();
  }
}


} // namespace GUC
} // namespace CPL

