using UVC.UI.Commands;

namespace UVC.UI.Toolbar.Model
{
    /// <summary>
    /// 툴바의 전체적인 데이터 컨테이너 및 관리 클래스입니다.
    /// 툴바에 표시될 모든 항목(IToolbarItem)들의 목록을 관리하며,
    /// 각 항목의 생성 및 초기 설정을 위한 헬퍼 메서드들을 제공합니다.
    /// 이 모델은 UI 표현(View)과 로직(Controller)으로부터 분리되어 툴바의 순수한 데이터 구조를 나타냅니다.
    /// </summary>
    /// <remarks>
    /// 역할:
    /// - 툴바 항목 저장: 툴바에 포함될 버튼, 구분선 등의 IToolbarItem 객체들을 리스트 형태로 보관합니다.
    /// - 툴바 항목 생성: AddStandardButton, AddToggleButton 등의 팩토리 메서드를 통해 특정 타입의 툴바 항목을 쉽게 생성하고 모델에 추가할 수 있도록 합니다.
    /// - 라디오 버튼 그룹 관리: 동일한 그룹 이름을 가진 ToolbarRadioButton들을 내부적으로 ToolbarRadioButtonGroup으로 묶어 관리합니다.
    /// 
    /// 사용 흐름:
    /// 1. Toolbar (또는 유사한 관리 클래스)에서 ToolbarModel의 인스턴스를 생성합니다.
    /// 2. 다양한 Add[ButtonType] 메서드 또는 AddItem 메서드를 호출하여 툴바 항목 모델들을 생성하고 ToolbarModel에 추가합니다.
    /// 3. 설정이 완료된 ToolbarModel 객체를 ToolbarView의 Initialize 메서드에 전달하여 UI를 렌더링하도록 합니다.
    /// </remarks>
    /// <example>
    /// <code>
    /// // Toolbar 등에서 ToolbarModel 사용 예시
    /// 
    /// // 1. ToolbarModel 인스턴스 생성
    /// ToolbarModel myToolbar = new ToolbarModel();
    /// 
    /// // 2. 표준 버튼 추가
    /// ICommand openCommand = new ActionCommand(() => Debug.Log("파일 열기 실행"));
    /// myToolbar.AddStandardButton("button_open_file", "icons/open", openCommand, "tooltip_open_file_description");
    /// 
    /// // 3. 구분선 추가
    /// myToolbar.AddSeparator();
    /// 
    /// // 4. 토글 버튼 추가
    /// myToolbar.AddToggleButton(
    ///     "button_toggle_grid", 
    ///     false, // 초기 상태 (꺼짐)
    ///     "icons/grid_on", // 켜짐 상태 아이콘
    ///     "icons/grid_off", // 꺼짐 상태 아이콘
    ///     (isSelected) => Debug.Log($"그리드 표시: {isSelected}"), // OnToggle 콜백
    ///     null, // ClickCommand (필요시 설정)
    ///     "tooltip_toggle_grid_visibility"
    /// );
    /// 
    /// // 5. 라디오 버튼 그룹 추가
    /// string viewModeGroup = "ViewModeSelection";
    /// myToolbar.AddRadioButton(viewModeGroup, "button_2d_view", true, "icons/2d_view", null, 
    ///     (isSelected) => { if(isSelected) Debug.Log("2D 뷰 선택됨"); }, 
    ///     null, "tooltip_2d_view");
    /// myToolbar.AddRadioButton(viewModeGroup, "button_3d_view", false, "icons/3d_view", null, 
    ///     (isSelected) => { if(isSelected) Debug.Log("3D 뷰 선택됨"); },
    ///     null, "tooltip_3d_view");
    /// 
    /// // 6. 설정된 모델을 ToolbarView에 전달
    /// // toolbarView.Initialize(myToolbar); 
    /// </code>
    /// </example>
    public class ToolbarModel
    {
        /// <summary>
        /// 툴바에 추가된 모든 항목(IToolbarItem)들의 리스트입니다.
        /// 이 리스트의 순서대로 툴바에 항목들이 표시됩니다.
        /// 외부에서는 읽기만 가능하도록 private set으로 설정되어 있으며, 항목 추가는 AddItem 또는 Add[ButtonType] 메서드를 통해 이루어집니다.
        /// </summary>
        public System.Collections.Generic.List<IToolbarItem> Items { get; private set; }

        /// <summary>
        /// 라디오 버튼 그룹들을 관리하는 딕셔너리입니다.
        /// 키는 라디오 버튼의 GroupName이며, 값은 해당 그룹을 관리하는 ToolbarRadioButtonGroup 객체입니다.
        /// ToolbarRadioButton이 AddItem을 통해 추가될 때 내부적으로 사용됩니다.
        /// </summary>
        private System.Collections.Generic.Dictionary<string, ToolbarRadioButtonGroup> _radioGroups;

        /// <summary>
        /// ToolbarModel의 새 인스턴스를 초기화합니다.
        /// Items 리스트와 _radioGroups 딕셔너리를 빈 상태로 생성합니다.
        /// </summary>
        public ToolbarModel()
        {
            Items = new System.Collections.Generic.List<IToolbarItem>();
            _radioGroups = new System.Collections.Generic.Dictionary<string, ToolbarRadioButtonGroup>();
        }

        /// <summary>
        /// 지정된 툴바 항목(IToolbarItem)을 모델에 추가합니다.
        /// 추가된 항목은 Items 리스트의 끝에 추가됩니다.
        /// 만약 추가되는 항목이 ToolbarRadioButton이라면, 해당 버튼을 적절한 ToolbarRadioButtonGroup에 등록하거나 새로 생성하여 관리합니다.
        /// </summary>
        /// <param name="item">툴바에 추가할 IToolbarItem 객체입니다 (예: ToolbarStandardButton, ToolbarSeparator 등).</param>
        public void AddItem(IToolbarItem item)
        {
            Items.Add(item);

            if (item is ToolbarRadioButton radioButton)
            {
                if (!_radioGroups.TryGetValue(radioButton.GroupName, out var group))
                {
                    group = new ToolbarRadioButtonGroup();
                    _radioGroups.Add(radioButton.GroupName, group);
                }
                group.RegisterButton(radioButton);
                radioButton.RadioGroup = group; // 버튼 모델에 그룹 참조 설정
                // 그룹 내 초기 선택 상태 결정 (만약 이 버튼이 initialState=true이고, 그룹에 아직 선택된 버튼이 없다면)
                // 또는 모든 버튼이 추가된 후 그룹별로 InitializeSelection()을 호출할 수도 있습니다.
                // 현재는 AddRadioButton 메서드에서 initialState에 따른 SetSelected 호출로 처리하고 있습니다.
            }
            // UI 갱신 로직은 ToolbarModel 자체에서는 직접 호출하지 않습니다.
            // View가 Model의 변경 사항을 구독하거나, Controller가 View의 업데이트를 트리거합니다.
            // 혹은, Model에 아이템이 추가/제거될 때 이벤트를 발생시켜 View가 감지하도록 할 수 있습니다.
        }

        /// <summary>
        /// 새로운 ToolbarStandardButton을 생성하여 툴바 모델에 추가합니다.
        /// </summary>
        /// <param name="text">버튼에 표시될 텍스트 또는 다국어 키입니다.</param>
        /// <param name="iconSpritePath">버튼 아이콘의 Resources 경로입니다 (선택 사항).</param>
        /// <param name="command">버튼 클릭 시 실행될 ICommand 객체입니다 (선택 사항).</param>
        /// <param name="tooltip">버튼 툴팁의 텍스트 또는 다국어 키입니다 (선택 사항).</param>
        /// <returns>생성되고 추가된 ToolbarStandardButton 객체입니다.</returns>
        public ToolbarStandardButton AddStandardButton(string text, string iconSpritePath = null, ICommand command = null, string tooltip = null)
        {
            var button = new ToolbarStandardButton { Text = text, IconSpritePath = iconSpritePath, ClickCommand = command, Tooltip = tooltip };
            AddItem(button);
            return button;
        }

        /// <summary>
        /// 새로운 ToolbarToggleButton을 생성하여 툴바 모델에 추가합니다.
        /// </summary>
        /// <param name="text">버튼 텍스트 또는 다국어 키입니다.</param>
        /// <param name="initialState">버튼의 초기 선택 상태입니다 (기본값: false, 해제됨).</param>
        /// <param name="onIconSpritePath">버튼이 선택(On) 상태일 때의 아이콘 경로입니다 (선택 사항).</param>
        /// <param name="offIconSpritePath">버튼이 해제(Off) 상태일 때의 아이콘 경로입니다 (선택 사항).</param>
        /// <param name="onToggle">버튼의 선택 상태가 변경될 때 호출될 콜백 함수입니다 (선택 사항).</param>
        /// <param name="command">버튼 클릭 시 실행될 ICommand 객체입니다 (선택 사항).</param>
        /// <param name="tooltip">버튼 툴팁의 텍스트 또는 다국어 키입니다 (선택 사항).</param>
        /// <returns>생성되고 추가된 ToolbarToggleButton 객체입니다.</returns>
        public ToolbarToggleButton AddToggleButton(string text, bool initialState = false, string onIconSpritePath = null, string offIconSpritePath = null, System.Action<bool> onToggle = null, ICommand command = null, string tooltip = null)
        {
            // ToolbarToggleButton의 IconSpritePath는 '선택된 상태'의 아이콘을 의미합니다.
            var button = new ToolbarToggleButton
            {
                Text = text,
                IsSelected = initialState,
                IconSpritePath = onIconSpritePath, // 선택 시 아이콘
                OffIconSpritePath = offIconSpritePath, // 해제 시 아이콘
                OnToggle = onToggle,
                ClickCommand = command,
                Tooltip = tooltip
            };
            AddItem(button);
            return button;
        }

        /// <summary>
        /// 새로운 ToolbarRadioButton을 생성하여 툴바 모델에 추가합니다.
        /// 동일한 groupName을 가진 라디오 버튼들은 하나의 그룹으로 동작합니다.
        /// </summary>
        /// <param name="groupName">이 라디오 버튼이 속할 그룹의 이름입니다.</param>
        /// <param name="text">버튼 텍스트 또는 다국어 키입니다.</param>
        /// <param name="initialState">버튼의 초기 선택 상태입니다. 같은 그룹 내에서 하나의 버튼만 true로 설정해야 합니다.</param>
        /// <param name="iconSpritePath">버튼이 선택(On) 상태일 때의 아이콘 경로입니다 (선택 사항).</param>
        /// <param name="offIconSpritePath">버튼이 해제(Off) 상태일 때의 아이콘 경로입니다 (선택 사항).</param>
        /// <param name="onToggle">버튼의 선택 상태가 변경될 때 호출될 콜백 함수입니다 (선택 사항).</param>
        /// <param name="command">버튼 클릭(선택) 시 실행될 ICommand 객체입니다 (선택 사항).</param>
        /// <param name="tooltip">버튼 툴팁의 텍스트 또는 다국어 키입니다 (선택 사항).</param>
        /// <returns>생성되고 추가된 ToolbarRadioButton 객체입니다.</returns>
        public ToolbarRadioButton AddRadioButton(string groupName, string text, bool initialState = false, string iconSpritePath = null, string offIconSpritePath = null, System.Action<bool> onToggle = null, ICommand command = null, string tooltip = null)
        {
            var button = new ToolbarRadioButton(groupName)
            {
                Text = text,
                IsSelected = initialState,// 초기 IsSelected 상태 설정
                IconSpritePath = iconSpritePath,// 선택 시 아이콘
                OffIconSpritePath = offIconSpritePath,// 해제 시 아이콘
                OnToggle = onToggle,
                ClickCommand = command,
                Tooltip = tooltip
            };

            // AddItem 내에서 그룹 등록 및 버튼에 그룹 참조 설정이 이루어집니다.
            AddItem(button);

            // initialState가 true인 경우, 해당 그룹 내에서 이 버튼을 명시적으로 선택된 상태로 만듭니다.
            // 이렇게 하면 여러 라디오 버튼 중 initialState가 true인 마지막 버튼이 최종 선택됩니다.
            // 또는, 그룹별로 모든 버튼이 추가된 후 한 번만 선택 로직을 실행하는 것도 방법입니다.
            if (initialState && _radioGroups.TryGetValue(groupName, out var group))
            {
                group.SetSelected(button);
            }
            return button;
        }

        /// <summary>
        /// 새로운 ToolbarExpandableButton(확장 가능한 버튼)을 생성하여 툴바 모델에 추가합니다.
        /// </summary>
        /// <param name="text">주 버튼에 표시될 텍스트 또는 다국어 키입니다.</param>
        /// <param name="iconSpritePath">주 버튼의 기본 아이콘 경로입니다 (선택 사항).</param>
        /// <param name="command">주 버튼 클릭 시 실행될 ICommand 객체입니다 (선택 사항, 하위 메뉴 토글과는 별개일 수 있음).</param>
        /// <param name="tooltip">주 버튼 툴팁의 텍스트 또는 다국어 키입니다 (선택 사항).</param>
        /// <returns>생성되고 추가된 ToolbarExpandableButton 객체입니다.</returns>
        public ToolbarExpandableButton AddExpandableButton(string text, string iconSpritePath = null, ICommand command = null, string tooltip = null)
        {
            var button = new ToolbarExpandableButton { Text = text, IconSpritePath = iconSpritePath, ClickCommand = command, Tooltip = tooltip };
            AddItem(button);
            return button;
        }

        // <summary>
        /// 새로운 ToolbarSeparator(구분선)를 생성하여 툴바 모델에 추가합니다.
        /// </summary>
        public void AddSeparator()
        {
            AddItem(new ToolbarSeparator());
        }

        // 만약 모든 라디오 버튼 그룹의 초기 선택 상태를 한 번에 설정하고 싶다면 다음과 같은 메서드를 추가할 수 있습니다.
        // /// <summary>
        // /// 모든 라디오 버튼 그룹에 대해 초기 선택 상태를 설정합니다.
        // /// 각 그룹에서 IsSelected가 true로 설정된 버튼이 없다면 첫 번째 버튼을 선택합니다.
        // /// </summary>
        // public void FinalizeRadioGroupSelections()
        // {
        //     foreach (var group in _radioGroups.Values)
        //     {
        //         group.InitializeSelection();
        //     }
        // }

        // 실제 UI 렌더링 및 상호작용 로직은 이 클래스 또는 별도의 UI View 클래스에서 처리됩니다.
        // (예: Unity UI GameObject 생성, 이벤트 연결 등)
    }
}
