/// ****************************************************************************
/// @file   
/// @author Dr.Neeton
/// @date   2010/X/X - 2017/02/01
/// 
/// @brief  アクティブフォーム表示管理コンポーネント関連。
/// 
/// ****************************************************************************


#include "CPL_GUC_ActiveManageComponent.h"
#include "CPL_GUC_Window.h"


namespace CPL {
namespace GUC {
  

// _____________________________________________________________________________
/// @copydoc CPL::GUC::Component::On_UserProc
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
eEventReturnID
  ActiveManageComponent::On_UserProc
    ( _in<sdptr<Component>> in_sp_component
    , _in<long            > in_message
    , _in<WPARAM          > in_wparam
    , _in<LPARAM          > in_lparam
    )
{
  switch( in_message )
  {
  case eID::ActiveViewItemShow:
    SetUniqueActiveForm( reinterpret_cast<ActiveForm*>(in_lparam) );
    break;

  case eID::ActiveViewItemHide:
    SetUniqueActiveForm( nullptr );
    break;

  default:
    SendParentMessage
      ( in_sp_component, in_message, in_wparam, in_lparam
      , eParentType::Position
      );
  }

  return eEventReturnID::LastCall;
}


// _____________________________________________________________________________
/// @copydoc CPL::GUC::MouseEventInterface::On_MouseEnter
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
eEventReturnID
  ActiveManageComponent::On_MouseEnter
    ( _in<sdptr<Component>> in_sp_comp_enter
    , _in<sdptr<Component>> in_sp_comp_leave
    )
{
  auto sp_active_form = GetComponent_ActiveForm();
  if( in_sp_comp_leave == GetLinkMyself()  &&  sp_active_form )
  {
    if( !sp_active_form->IsVisible() )
    {
      //
      sp_active_form->SetStateVisible( true );
    }
  }
  return eEventReturnID::LastCall;
}


// _____________________________________________________________________________
/// @brief アクティブフォームを全体で一つ表示させるための処理関数。
/// 
/// @param[in] in_ptr_active_form
///   : 新しくアクティブにするフォームコンテナ。\n
///   : nullptrを指定すると、全てのアクティブフォームを非表示にする。
/// 
/// @return なし。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void
  ActiveManageComponent::SetUniqueActiveForm
    ( pin<ActiveForm> in_ptr_active_form )
{
  auto sp_active_form = sm_wp_active_form().lock();
  if( in_ptr_active_form  &&
      sp_active_form == in_ptr_active_form->GetLinkMyself() )
  {
    return;
  }

  if( sp_active_form )
  {
    sp_active_form->SetStateVisible( false );
    if( in_ptr_active_form == nullptr )
    {
      sm_wp_active_form().reset();
      return;
    }
    else
    {
//->      int f_child = sm_wp_active_form()->IsChild( in_ptr_ac_form );
//->      if( !f_child )
//->      {
//->        ActiveForm* ptr_ac_form = &*sm_wp_active_form();
//->        sm_wp_active_form() = nullptr;
//->        ptr_ac_form->SetStateVisible( false );
//->      }
    }
  }

  if( in_ptr_active_form )
  {
    sm_wp_active_form() =
      std::dynamic_pointer_cast<ActiveForm>(in_ptr_active_form->GetLinkMyself());
  }
}


// _____________________________________________________________________________
/// @copydoc CPL::GUC::Component::CreateClone
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sdptr<Component>
  ActiveManageComponent::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 コンストラクタ
/// 
/// @copydoc doxycomment::arg_in_sp_component_for_parent
/// @copydoc doxycomment::arg_in_position_for_component
/// @copydoc doxycomment::arg_in_size_for_component
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ActiveManageComponent::ActiveManageComponent
( _in<sdptr<Component>> in_sp_component_for_parent
, _in<float2          > in_position_for_component
, _in<float2          > in_size_for_component
) : Container
    ( in_sp_component_for_parent
    , in_position_for_component
    , in_size_for_component
    )
{
  zzf_setupDrawState( false, false, false ); // 描画ステートのデフォルト設定。
}


// _____________________________________________________________________________
/// @brief コピーコンストラクタ
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ActiveManageComponent::ActiveManageComponent
( cref<ActiveManageComponent> in_active_manage_component
) : Container( in_active_manage_component )
{
  // オリジナルのアクティブフォームの取得とチェック。
  auto sp_active_form_for_original =
    in_active_manage_component.m_wp_active_form.lock();
  if( sp_active_form_for_original )
  {
    // アクティブフォームが存在する場合、まず検索し、複製されていたらそのまま適用、
    // 複製されていない場合、新しく作成する。
    m_wp_active_form =
      FindComponentT_by_UserID<ActiveForm>( sp_active_form_for_original );
    if( m_wp_active_form.expired() )
    {
      // アクティブフォーム作成
      m_wp_active_form =
        sp_active_form_for_original->CreateCloneT<ActiveForm>( GetLinkMyself() );
      m_wp_active_form.lock()->SetBelongComponent
        ( sp_active_form_for_original->GetBelongComponent( eParentType::Render )
        , eParentType::Render
        );
    }
    m_wp_active_form.lock()->SetAutoUserID();
  }
}





// _____________________________________________________________________________
/// @brief コンストラクタ
/// 
/// @copydoc doxycomment::arg_in_sp_component_for_parent
/// @copydoc doxycomment::arg_in_position_for_component
/// @param[in] in_text
///   : 表示文字列を指定します。
/// @param[in] in_sp_item_container
///   : アイテムとして配置するコンポーネントを指すスマートポインタを指定します。
/// @param[in] in_flag_expand_mode
///   : 初期の展開状態フラグを指定します。\n
///   : -1 : なし。           \n
///   :  0 : 閉じた状態。     \n
///   :  1 : 開いた状態。
/// @param[in] in_pos_mode
///   : 位置モードフラグを指定します。\n
///   : 詳しくはActiveForm::ePosModeを参照してください。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ActiveFormManager::ActiveFormManager
( _in<sdptr<Component>    > in_sp_component_for_parent
, _in<float2              > in_position_for_component
, _in<td_DefString        > in_text
, _in<sdptr<Container>    > in_sp_item_container
, _in<int                 > in_flag_expand_mode
, _in<ActiveForm::ePosMode> in_pos_mode
) : ActiveManageComponent
    ( in_sp_component_for_parent
    , in_position_for_component
    , kSIZE_DEFAULT
    )
  , m_flag_expand( in_flag_expand_mode ) // m_flag_expandは開閉状態を保持するフラグだが、この時点ではモードを保持しておく
  , m_sp_item_container( in_sp_item_container )
  , m_text( in_text )
{
  sdptr<Component> sp_comp_myself = GetLinkMyself();
  if( m_flag_expand >= 0 )
  {
    // ボタン作成
    m_sp_btn_expand =
      Factory<GUC::Button>::Create
        ( sp_comp_myself
        , float2(2,2)
        , float2(12,12)
        , CPL_GUC_DEF_STR("＋")
        , nullptr
        );
  }
  if( m_sp_item_container )
  {
    // アイテムフォームの親変更（自身の子供ノードに移動）
    //getThisSmPtr().AddNodeChild( m_wp_item_container );
    m_sp_item_container->SetBelongComponent
      ( sp_comp_myself
      , eParentType::Position
      );
    // アイテムの位置修正
    m_sp_item_container->SetPosition
      ( float2{ 1, Window::GetTitleHeight() }
      );
  }
  // アクティブフォーム作成
  m_wp_active_form =
    Factory<ActiveForm>::Create( sp_comp_myself, in_pos_mode );

  zzf_setupDrawState( false, false, true ); // 描画ステートのデフォルト設定。
  zzf_SetInitializedLevel( zzf_GetClassLevel() );

  AdjustSize( float2(2,2) );
}


// _____________________________________________________________________________
/// @brief コピーコンストラクタ
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ActiveFormManager::ActiveFormManager
( cref<ActiveFormManager> in_active_form_manager
) : ActiveManageComponent( in_active_form_manager )
  , m_sp_item_container
    ( FindComponentT_by_UserID<Container>( in_active_form_manager.m_sp_item_container )
    )
  , m_sp_btn_expand
    ( FindComponentT_by_UserID<Button>( in_active_form_manager.m_sp_btn_expand )
    )
  , m_flag_expand( in_active_form_manager.m_flag_expand )
  , m_text( in_active_form_manager.m_text )
{
  m_sp_item_container->SetAutoUserID();
  m_sp_btn_expand    ->SetAutoUserID();
}


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

/*
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// アクティブフォームマネージャ　ボタンイベント
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
long ActiveFormManager::On_Button( WIN::Button* in_ptr_button, int in_flag_down )
{
  if( in_flag_down )
  {
    return false;
  }

  if( m_wp_btn_expand == in_ptr_button )
  {
    m_flag_expand = !m_flag_expand;
    
    if( !m_flag_expand )
    {
      m_wp_btn_expand->SetTitle( SwS("＋") );

      WIN::Rect rt_clt;
      this->GetClientRect( &rt_clt );
      rt_clt.bottom = rt_clt.top + title_h;
      SetWindowSize( short(rt_clt.GetWidth()), short(rt_clt.GetHeight()) );
    }
    else
    {
      CPL_SAFE_PTR(m_wp_active_form)->Show( false );
      m_wp_btn_expand->SetTitle( SwS("−") );
      // アイテムを自身に再配置
      m_wp_item_container->SetParent( this );
      m_wp_item_container->SetPosition( 1, title_h );

      //
      AdjustSize( float2(2,2) );
    }

    SendParentMessage( WIN::WM_CPL_GROUPBOX_EXPAND, 0, reinterpret_cast<LPARAM>(this) );

    Update();
  }

  return false;
}
*/

// _____________________________________________________________________________
/// @copydoc CPL::GUC::Component::On_Size
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
eEventReturnID
  ActiveFormManager::On_Size( _in<sdptr<Component>> in_sp_component )
{
  if( in_sp_component == GetLinkMyself() )
  {
    if( m_sp_btn_expand == nullptr )
    {
      return eEventReturnID::LastCall;
    }

    float4 rt_clt = GetRectCoord();
    //
    auto title = m_text;
    //
    if( !m_flag_expand  &&  title.Comp( CPL_GUC_DEF_STR("") ) )
    {
      rt_clt.w = rt_clt.y + Window::GetTitleHeight();
      SetSize( float2(rt_clt.Width(), rt_clt.Height()) );
    }
    else
    {
      rt_clt.z -= 2;
  /*    baseCommonContainer* ptr_common_cont =
        dynamic_cast<baseCommonContainer*>(&*m_wp_item_container);
      if( ptr_common_cont )
      {
        int num = ptr_common_cont->GetCompNum();
        for( int i = 0; i < num; ++i )
        {
          ptr_common_cont->zzf_getComp(i)->SetWindowRect( &rt_clt, false, eRectFlag::Right );
        }
      }*/
      CPL_SAFE_PTR(m_sp_item_container)
        ->SetRectCoord( rt_clt, WIN::Component::eRectFlag::Right );
    }
  }

  return eEventReturnID::SendParent_Position;
}

// _____________________________________________________________________________
/// @copydoc CPL::GUC::MouseEventInterface::On_MouseEnter
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
eEventReturnID
  ActiveFormManager::On_MouseEnter
    ( _in<sdptr<Component>> in_sp_comp_enter
    , _in<sdptr<Component>> in_sp_comp_leave
    )
{
  if( auto sp_active_form = m_wp_active_form.lock() )
  {
    if( !m_flag_expand  &&  !sp_active_form->IsVisible() )
    {
      if( m_sp_item_container )
      {
        // コンテナをアクティブビューに移動
        m_sp_item_container->SetBelongComponent
          ( sp_active_form
          , eParentType::Render
          );
        m_sp_item_container->SetPosition( float2(0, 0) );
        //
        sp_active_form->AdjustSize();
        sp_active_form->SetStateVisible( true );
      }
    }
  }
  return eEventReturnID::LastCall;
}


// _____________________________________________________________________________
/// @copydoc CPL::GUC::MouseEventInterface::On_MouseUp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
eEventReturnID
  ActiveFormManager::On_MouseUp
    ( _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 == m_sp_btn_expand )
  {
    m_flag_expand = !m_flag_expand;
    
    if( !m_flag_expand )
    {
      m_sp_btn_expand->SetText( CPL_GUC_DEF_STR("＋") );

      auto rt_clt = GetRectCoord();
      rt_clt.w = rt_clt.y + this->GetLineHeight();
      SetSize( float2(rt_clt.Width(), rt_clt.Height()) );
    }
    else
    if( auto sp_active_form = m_wp_active_form.lock() )
    {
      sp_active_form->SetStateVisible( false );
      m_sp_btn_expand->SetText( CPL_GUC_DEF_STR("−") );
      // アイテムを自身に再配置。
      AddLinkChild( m_sp_item_container );
      m_sp_item_container->SetPosition
        ( float2( 1, GetLineHeight() )
        );

      //
      AdjustSize( float2(2,2) );
    }

//    SendParentMessage( getThisSmPtr(), eID::ExpandForm, 0, reinterpret_cast<LPARAM>(this) );

    Update();
  }


  return eEventReturnID::SendParent_Position;
}



// _____________________________________________________________________________
/// @copydoc CPL::GUC::Component::On_DrawClient
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void ActiveFormManager::On_DrawClient( _in<float4> in_rect )
{
  // テキスト描画
//#ifdef CPL_UNICODE
  DX::FontDrawManager::MsgInfo
    mi( this->GetText()
      , WIN::Rect
          ( static_cast<long>(in_rect.x) + 2
          , static_cast<long>(in_rect.y) + 2
          , -1
          , -1
          )
      );
//#else
//  DX::FontDrawManager::MsgInfo
//    mi( Core::ChangeCodeStrings( Core::StringW(), this->GetText() )
//      , &WIN::Rect
//          ( static_cast<long>(in_rect.x) + 2
//          , static_cast<long>(in_rect.y) + 2
//          , -1
//          , -1
//          )
//      );
//#endif

  sm_def_font_mng()->DrawMessage( mi );

  sm_def_font_mng()->Translate( sm_ptr_d3ddev() );
}




} // namespace GUC
} // namespace CPL

