using System;

namespace UVC.UI.Toolbar.Model
{
    /// <summary>
    /// 클릭할 때마다 선택(On) 또는 해제(Off) 상태가 전환되는 토글 버튼입니다.
    /// ToolbarButtonBase를 상속받으며, 추가적으로 선택 상태(IsSelected)와
    /// 해제 상태일 때의 아이콘 경로(OffIconSpritePath), 상태 변경 시 호출될 콜백(OnToggle)을 관리합니다.
    /// </summary>
    /// <remarks>
    /// View 레이어(예: ToolbarView)에서는 이 모델에 해당하는 UI 요소(예: UnityEngine.UI.Toggle)를 생성하고,
    /// 사용자가 UI 토글을 조작하면 이 모델의 ExecuteClick 메서드를 호출하거나 IsSelected 속성을 직접 변경하여
    /// 모델과 UI의 상태를 동기화합니다. IsSelected 속성이 변경되면 OnStateChanged 및 OnToggleStateChanged 이벤트가 발생하여
    /// View가 아이콘(선택/해제 상태에 따라 IconSpritePath 또는 OffIconSpritePath 사용) 및 기타 시각적 요소를 업데이트합니다.
    /// </remarks>
    /// <example>
    /// <code>
    /// // Toolbar 또는 ToolbarModel 등에서 ToolbarToggleButton 생성 및 사용 예시
    /// 
    /// // 1. 토글 상태 변경 시 실행될 액션 정의 (OnToggle 콜백용)
    /// Action<bool> handleMuteToggle = (isMuted) =>
    /// {
    ///     UnityEngine.Debug.Log(isMuted ? "음소거됨" : "음소거 해제됨");
    ///     // 여기에 실제 음소거/해제 로직 구현
    /// };
    /// 
    /// // 2. 토글 버튼 클릭 시 실행될 커맨드 정의 (선택 사항, 주로 상태 변경 후 추가 작업)
    /// // 이 커맨드는 IsSelected 상태가 변경된 *후에* ExecuteClick 내부에서 호출됩니다.
    /// // 커맨드 파라미터로 현재 IsSelected 상태를 받고 싶다면 ActionCommand<bool> 사용 가능.
    /// ICommand muteCommand = new ActionCommand<bool>((isSelected) => 
    /// {
    ///     UnityEngine.Debug.Log($"음소거 버튼 커맨드 실행됨. 현재 선택 상태: {isSelected}");
    /// });
    /// 
    /// // 3. ToolbarToggleButton 인스턴스 생성 및 속성 설정
    /// ToolbarToggleButton muteToggleButton = new ToolbarToggleButton
    /// {
    ///     Text = "button_mute", // 버튼 텍스트 (다국어 키)
    ///     IconSpritePath = "icons/toolbar/sound_on_icon",  // 선택(On) 상태 아이콘
    ///     OffIconSpritePath = "icons/toolbar/sound_off_icon", // 해제(Off) 상태 아이콘
    ///     Tooltip = "tooltip_mute_button", // 툴팁 (다국어 키)
    ///     IsSelected = false, // 초기 상태는 해제(Off)
    ///     OnToggle = handleMuteToggle, // 상태 변경 시 콜백 할당
    ///     ClickCommand = muteCommand, // 클릭 커맨드 할당
    ///     IsEnabled = true // 버튼 활성화 상태
    /// };
    /// 
    /// // 4. 생성된 버튼 모델을 ToolbarModel에 추가
    /// // toolbarModel.AddItem(muteToggleButton);
    /// // 또는
    /// // toolbarModel.AddToggleButton("button_mute", false, "icons/toolbar/sound_on_icon", "icons/toolbar/sound_off_icon", handleMuteToggle, muteCommand, "tooltip_mute_button");
    /// 
    /// // 5. 버튼 상태 프로그래밍 방식으로 변경 예시
    /// // muteToggleButton.IsSelected = true; // 버튼을 선택 상태로 변경 (OnToggle 콜백 및 이벤트 발생)
    /// </code>
    /// </example>
    public class ToolbarToggleButton : ToolbarButtonBase
    {
        /// <summary>
        /// 버튼의 선택 상태(IsSelected)가 변경될 때 발생하는 이벤트입니다.
        /// 변경된 IsSelected 값을 파라미터로 전달합니다.
        /// View에서 이 이벤트를 구독하여 UI의 시각적 상태(예: Toggle 컴포넌트의 isOn 상태)를 업데이트할 수 있습니다.
        /// OnStateChanged 이벤트와 별개로, IsSelected 상태 변경에 좀 더 특화된 알림입니다.
        /// </summary>
        public event Action<bool> OnToggleStateChanged; // IsSelected 변경 시 IsSelected 값을 전달하는 이벤트

        protected string _offIconSpritePath;
        /// <summary>
        /// 버튼이 선택되지 않은(해제된, Off) 상태일 때 표시될 아이콘의 Resources 폴더 내 경로입니다.
        /// 이 값이 변경되면 OnStateChanged 이벤트가 발생하여 View가 아이콘을 업데이트할 수 있습니다.
        /// 선택(On) 상태일 때는 ToolbarButtonBase의 IconSpritePath가 사용됩니다.
        /// </summary>
        public string OffIconSpritePath
        {
            get => _offIconSpritePath;
            set
            {
                if (_offIconSpritePath != value)
                {
                    _offIconSpritePath = value;
                    NotifyStateChanged();// 아이콘 경로 변경 시 전체 상태 변경으로 간주
                }
            }
        }

        private bool _isSelected;
        /// <summary>
        /// 버튼의 현재 선택 상태를 나타냅니다. true이면 선택(On)된 상태, false이면 해제(Off)된 상태입니다.
        /// 이 속성 값이 변경되면 OnStateChanged 이벤트와 OnToggleStateChanged 이벤트가 발생하며,
        /// OnToggle 콜백이 호출됩니다.
        /// </summary>
        public bool IsSelected
        {
            get => _isSelected;
            set
            {
                if (_isSelected != value)
                {
                    _isSelected = value;
                    OnToggle?.Invoke(_isSelected); // OnToggle 콜백 호출
                    OnToggleStateChanged?.Invoke(_isSelected); // IsSelected 값과 함께 이벤트 발생
                    NotifyStateChanged(); // 일반 상태 변경 이벤트도 발생
                }
            }
        }

        /// <summary>
        /// 버튼의 선택 상태(IsSelected)가 변경될 때 호출될 사용자 정의 콜백 액션입니다.
        /// IsSelected 속성의 setter 내부에서 호출됩니다.
        /// </summary>
        /// <remarks>
        /// ClickCommand와는 별개로, 순수하게 토글 상태 변경에 대한 응답 로직을 정의할 때 유용합니다.
        /// 예를 들어, UI 상태 변경에 따른 즉각적인 모델 데이터 변경 등에 사용할 수 있습니다.
        /// </remarks>
        public Action<bool> OnToggle { get; set; }

        /// <summary>
        /// 버튼 클릭 로직을 실행합니다.
        /// 토글 버튼의 경우, 클릭 시 IsSelected 상태를 반전시키고,
        /// ClickCommand가 있다면 현재 IsSelected 상태를 파라미터로 전달하여 실행합니다.
        /// </summary>
        /// <param name="parameter">
        /// 이 파라미터는 일반적으로 사용되지 않거나 무시될 수 있습니다. 
        /// ClickCommand에는 현재 IsSelected 상태가 전달됩니다.
        /// 만약 외부에서 특정 값을 전달해야 한다면, ClickCommand가 ActionCommand<object> 등으로 정의되어야 합니다.
        /// </param>
        public override void ExecuteClick(object parameter = null)
        {
            if (!IsEnabled) return;

            if (parameter is bool newSelectedStateFromUI)
            {
                // UI로부터 직접 상태가 전달된 경우 (View의 onValueChanged 리스너)
                // IsSelected 프로퍼티 setter가 OnToggle 및 NotifyStateChanged를 호출
                IsSelected = newSelectedStateFromUI;
            }
            else
            {
                // 일반적인 ExecuteClick (파라미터 없거나 bool이 아님) - 기존 토글 로직
                IsSelected = !IsSelected;
            }

            // ClickCommand 실행. IsSelected 상태가 변경된 *후에* 실행됩니다.
            // ClickCommand에 현재 선택 상태(IsSelected)를 파라미터로 전달합니다.
            // 만약 ClickCommand가 파라미터를 받지 않는 ActionCommand라면, 파라미터 없이 실행됩니다.
            // ClickCommand가 ActionCommand<bool>이라면 IsSelected 값이 전달됩니다.
            // ClickCommand가 ActionCommand<object>라면 IsSelected 값이 object로 박싱되어 전달됩니다.
            if (ClickCommand != null)
            {
                // ClickCommand의 구체적인 타입(제네릭 여부 등)에 따라 파라미터 전달 방식이 달라질 수 있습니다.
                // 가장 일반적인 경우는 ClickCommand가 현재 상태를 알 수 있도록 하는 것입니다.
                // ToolbarView에서 연결 시 new ActionCommand<bool>((isSelectedParam) => { /* 로직 */ }) 형태로 커맨드를 생성했다면,
                // isSelectedParam으로 현재 IsSelected 값이 전달됩니다.
                ClickCommand.Execute(IsSelected);
            }
        }

        /// <summary>
        /// 이 버튼 모델에 연결된 모든 이벤트 핸들러를 정리합니다.
        /// ToolbarButtonBase의 이벤트 외에 ToolbarToggleButton에 특화된 이벤트(OnToggleStateChanged, OnToggle)를 추가로 정리합니다.
        /// </summary>
        public override void ClearEventHandlers()
        {
            base.ClearEventHandlers(); // 부모 클래스의 이벤트 정리 (OnStateChanged)
            OnToggleStateChanged = null;
            OnToggle = null;
        }
    }
}
