/// ****************************************************************************
/// @file   
/// @author Dr.Neeton
/// @date   2010/X/X - 2015/11/19
/// 
/// @brief  リストボックスコンポーネント。
/// 
/// ****************************************************************************

#pragma once

#include "CPL_GUC_RenderOwner.h"
#include "CPL_GUC_ScrollBar.h"


namespace CPL {
namespace GUC {

typedef RenderOwner CPl_GUC_LIST_BOX_BASE;
// _____________________________________________________________________________
/// @brief リストボックス描画コンポーネント
///
// *****************************************************************************
class ListBox
  : public RenderOwner
{
  using td_base = RenderOwner;
  using td_self = ListBox;
  friend Factory<td_self>;
  friend CallPrivateConstructor<td_self>;

public:
  //CPL_GUC_DECL_BASIC_SMARTPOINTER( ListBox );

  static sdptr<DrawColorSet> GetDefaultColor_ListBoxBG();
  static sdptr<DrawColorSet> GetDefaultColor_ListBoxFrame();
  static sdptr<DrawColorSet> GetDefaultColor_ListBoxText();
  sdptr<DrawColorSet> GetDefaultColor_BG()   { return GetDefaultColor_ListBoxBG(); }
  sdptr<DrawColorSet> GetDefaultColor_Frame(){ return GetDefaultColor_ListBoxFrame(); }
  sdptr<DrawColorSet> GetDefaultColor_Text() { return GetDefaultColor_ListBoxText(); }

protected:
  using WpComponent = wkptr<Component>;
  struct ItemInfo {
    WpComponent wp_comp;
    bool        is_select = false;

    ItemInfo(){}
    ItemInfo( _in<WpComponent> in_wp_comp, bool in_is_select )
      : wp_comp( in_wp_comp )
      , is_select( in_is_select )
    {}
  };
  using ItemTable = std::vector<ItemInfo>;

  static int zzf_GetClassLevel(){
    return td_base::zzf_GetClassLevel() + 1; }

  size_t    m_select_idx0 = -1; // 選択中の最小インデックス(高速化用)。
  size_t    m_select_idx1 = -1; // 選択中の最大インデックス(高速化用)。
  size_t    m_item_max_h  = 0;
  ItemTable m_item_table; // 保持アイテムを選択情報込みで配列として持つ。

  void On_DrawBackground( _in<float4> in_rect ) override;
  void On_DrawFrame     ( _in<float4> in_rect ) override;

  eEventReturnID
    On_MouseDown
      ( _in<sdptr<Component>> in_sp_component
      , _in<float           > in_mouse_x
      , _in<float           > in_mouse_y
      , _in<eMouseButton    > in_type_mouse_btn
      ) override;
  eEventReturnID
    On_MouseWheel
      ( _in<sdptr<Component>> in_sp_component
      , _in<WORD            > in_fw_keys
      , _in<short           > in_z_delta
      );
  eEventReturnID
    On_Size( _in<sdptr<Component>> in_sp_component ) override;
  //eEventReturnID
  //  On_UserProc
  //    ( _in<sdptr<Component>> in_sp_component
  //    , _in<long            > in_message
  //    , _in<WPARAM          > in_wparam
  //    , _in<LPARAM          > in_lparam
  //    ) override;
  eEventReturnID
    On_KeyDown
      ( _in<sdptr<Component>> in_sp_component
      , _in<int             > in_virtual_key_code
      ) override;

protected:
  // _____________________________________________________________________________
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  ListBox
  ( _in<sdptr<Component>> in_sp_component_for_parent
  , _in<float2          > in_position_for_component
  , _in<float2          > in_size_for_component
  );
  // _____________________________________________________________________________
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  ListBox( cref<td_self> in_listbox );

  // _____________________________________________________________________________
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  void   zzz_AdjustSelectIndex( _in<size_t> in_index, _in<bool> in_flag_select );

public:
  // _____________________________________________________________________________
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  ~ListBox(){};

  // _____________________________________________________________________________
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  sdptr<Component>
    CreateClone
      ( _in<sdptr<Component>> in_sp_component_for_parent       = nullptr
      , _in<float2          > in_offset_position_from_original = float2{0,0}
      ) const override;

  virtual sdptr<Component>
    AddItem
      ( pin<td_DefChar> in_string_for_label
      , _in<size_t    > in_insert_idx = -1
      );
  virtual sdptr<Component> AddItem( _in<sdptr<Component>> in_sp_component, _in<size_t> in_insert_idx = -1 );
  virtual sdptr<Component> GetSelectItem() const;
  virtual size_t           GetSelectItemList( rout<std::vector<sdptr<Component>>> out_select_table ) const;
  virtual auto             GetSelectItemList() const ->std::vector<sdptr<Component>>;
  virtual sdptr<Component> GetItem( _in<size_t> in_index ) const;
  virtual size_t           GetItemNum() const;
  virtual size_t           FindItemComponentIndex( _in<sdptr<Component>> in_sp_component ) const;
  virtual bool             SetSelectItem( _in<size_t> in_index );
  virtual bool             SetSelectItem( _in<sdptr<Component>> in_sp_component );
  virtual bool             AddSelectItem( _in<size_t> in_index );
  virtual bool             AddSelectItem( _in<sdptr<Component>> in_sp_component );
  virtual void             Release();
  virtual bool             DeleteItem( _in<size_t> in_delete_index );
  virtual bool             DeleteItem( _in<sdptr<Component>> in_comp_delete );
  virtual bool             DeleteSelectItem();
  virtual bool             ChangeItem( _in<size_t> in_change_index, _in<sdptr<Component>> in_sp_component_of_new );
  virtual bool             ChangeItem( _in<sdptr<Component>> in_comp_old, _in<sdptr<Component>> in_sp_component_of_new );
  virtual void             AutoRepositionItems();
  //virtual void             SetActiveColor( _in<sdptr<DrawColorSet>> in_sp_color_active ){ m_sp_active_color = in_sp_color_active; }
  //virtual void             SetNormalColor( _in<sdptr<DrawColorSet>> in_sp_color_normal ){ m_sp_normal_color = in_sp_color_normal; }
};

//CPL_GUC_DECL_BASIC_SMARTPOINTER( ListBox );



} // namespace GUC
} // namespace CPL
