using System;
using UVC.UI.Commands;

namespace UVC.UI.Toolbar.Model
{
    /// <summary>
    /// 툴바에 사용되는 모든 버튼(표준 버튼, 토글 버튼, 확장 버튼 등)의 기본 추상 클래스입니다.
    /// IToolbarItem 인터페이스를 구현하여 툴바 시스템의 일부가 됩니다.
    /// 버튼이 가져야 할 공통적인 속성(예: 텍스트, 아이콘 경로, 활성화 상태, 툴팁 키)과
    /// 기본적인 동작(예: 클릭 시 커맨드 실행, 상태 변경 알림)을 정의합니다.
    /// 
    /// 이 클래스를 상속받아 특정 유형의 버튼(예: ToolbarStandardButton, ToolbarToggleButton)을 구현할 수 있습니다.
    /// </summary>
    /// <example>
    /// <code>
    /// // ToolbarButtonBase를 상속받는 사용자 정의 버튼 예시
    /// public class MyCustomButton : ToolbarButtonBase
    /// {
    ///     public string CustomProperty { get; set; }
    /// 
    ///     public MyCustomButton(string text, string iconPath, ICommand command, string tooltip = null)
    ///     {
    ///         Text = text; // 부모 클래스의 Text 속성 사용
    ///         IconSpritePath = iconPath; // 부모 클래스의 IconSpritePath 속성 사용
    ///         ClickCommand = command; // 부모 클래스의 ClickCommand 속성 사용
    ///         Tooltip = tooltip; // 부모 클래스의 Tooltip 속성 사용
    ///         IsEnabled = true; // 기본적으로 활성화 상태로 설정
    ///     }
    /// 
    ///     public override void ExecuteClick(object parameter = null)
    ///     {
    ///         if (!IsEnabled) return; // 비활성화 상태면 아무것도 하지 않음
    /// 
    ///         Debug.Log($"MyCustomButton '{Text}' clicked!");
    ///         // 기본 클릭 로직 실행 (예: ClickCommand 실행)
    ///         base.ExecuteClick(parameter); 
    /// 
    ///         // 이 버튼만의 추가적인 로직 수행
    ///         // PerformCustomAction();
    ///     }
    /// }
    /// 
    /// // 사용 예
    /// // ICommand saveCommand = new ActionCommand(() => { Debug.Log("Save action triggered!"); });
    /// // MyCustomButton saveButton = new MyCustomButton("Save", "icons/save_icon", saveCommand, "Save the current file");
    /// // toolbarModel.AddItem(saveButton);
    /// </code>
    /// </example>
    public abstract class ToolbarButtonBase : IToolbarItem
    {
        /// <summary>
        /// 버튼의 상태(예: Text, IconSpritePath, IsEnabled)가 변경되었을 때 발생하는 이벤트입니다.
        /// View 레이어(예: ToolbarView)는 이 이벤트를 구독하여 버튼의 시각적 표현을 업데이트합니다.
        /// </summary>
        /// <remarks>
        /// 속성(Text, IconSpritePath, IsEnabled)의 setter 내부에서 자동으로 호출됩니다.
        /// 여러 상태를 한 번에 변경한 후 수동으로 알리고 싶다면 NotifyStateChanged() 메서드를 사용할 수 있습니다.
        /// </remarks>
        public event Action OnStateChanged;

        protected string _text;
        /// <summary>
        /// 버튼에 표시될 텍스트 또는 텍스트의 다국어 키입니다.
        /// 값이 변경되면 OnStateChanged 이벤트가 발생합니다.
        /// </summary>
        /// <example>
        /// <code>
        /// button.Text = "새 작업"; // 직접 텍스트 설정
        /// button.Text = "toolbar_button_new_task_key"; // 다국어 키 설정 (LocalizationManager가 이 키를 실제 텍스트로 변환)
        /// </code>
        /// </example>
        public string Text
        {
            get => _text;
            set
            {
                if (_text != value)
                {
                    _text = value;
                    OnStateChanged?.Invoke();
                }
            }
        }

        protected string _iconSpritePath;
        /// <summary>
        /// 버튼에 표시될 아이콘의 Resources 폴더 내 경로입니다 (확장자 제외).
        /// 값이 변경되면 OnStateChanged 이벤트가 발생합니다.
        /// 아이콘이 없는 경우 null 또는 빈 문자열로 설정할 수 있습니다.
        /// </summary>
        /// <example>
        /// <code>
        /// button.IconSpritePath = "ToolbarIcons/OpenIcon"; // Resources/ToolbarIcons/OpenIcon.png (또는 다른 지원 형식)
        /// </code>
        /// </example>
        public string IconSpritePath
        {
            get => _iconSpritePath;
            set
            {
                if (_iconSpritePath != value)
                {
                    _iconSpritePath = value;
                    OnStateChanged?.Invoke();
                }
            }
        }

        protected bool _isEnabled = true;
        /// <summary>
        /// 버튼의 활성화 상태를 나타냅니다. true이면 사용자와 상호작용할 수 있고, false이면 비활성화되어 상호작용할 수 없습니다.
        /// 값이 변경되면 OnStateChanged 이벤트가 발생합니다.
        /// </summary>
        /// <example>
        /// <code>
        /// button.IsEnabled = false; // 버튼 비활성화
        /// if (button.IsEnabled) { /* 버튼 사용 가능 로직 */ }
        /// </code>
        /// </example>
        public bool IsEnabled
        {
            get => _isEnabled;
            set
            {
                if (_isEnabled != value)
                {
                    _isEnabled = value;
                    OnStateChanged?.Invoke();
                }
            }
        }

        protected string _tooltip;
        /// <summary>
        /// 버튼에 마우스를 올렸을 때 표시될 툴팁의 텍스트 또는 다국어 키입니다.
        /// Tooltip 변경 시에는 기본적으로 OnStateChanged 이벤트가 발생하지 않지만,
        /// 필요에 따라 View에서 이 값을 직접 참조하여 툴팁을 업데이트할 수 있습니다.
        /// </summary>
        /// <example>
        /// <code>
        /// button.Tooltip = "tooltip_save_button"; // 다국어 키 사용
        /// button.Tooltip = "클릭하여 문서를 저장합니다."; // 직접 텍스트 사용
        /// </code>
        /// </example>
        public string Tooltip
        {
            get => _tooltip;
            set
            {
                if (_tooltip != value)
                {
                    _tooltip = value;
                    // Tooltip 변경 시 OnStateChanged를 호출할 필요는 일반적으로 없으나,
                    // 만약 UI가 Tooltip 자체를 표시하는 등의 로직이 있다면 필요할 수 있습니다.
                    // 여기서는 툴팁 내용이 동적으로 변경되는 경우가 적다고 가정하고 생략합니다.
                    // 필요하다면 OnStateChanged?.Invoke(); 추가
                }
            }
        }

        /// <summary>
        /// 버튼이 클릭되었을 때 실행될 동작을 정의하는 커맨드 객체입니다.
        /// ICommand 인터페이스를 구현한 객체를 할당합니다 (예: ActionCommand).
        /// </summary>
        /// <example>
        /// <code>
        /// // ActionCommand를 사용하여 간단한 동작 정의
        /// button.ClickCommand = new ActionCommand(() => 
        /// {
        ///     Debug.Log($"'{button.Text}' 버튼이 클릭되었습니다.");
        ///     // 특정 기능 수행
        /// });
        /// 
        /// // 파라미터가 있는 커맨드
        /// button.ClickCommand = new ActionCommand<string>((fileName) => 
        /// {
        ///     Debug.Log($"파일 열기: {fileName}");
        /// });
        /// // ExecuteClick 메서드 호출 시 파라미터 전달 필요
        /// // button.ExecuteClick("MyDocument.txt"); 
        /// </code>
        /// </example>
        public ICommand ClickCommand { get; set; }

        /// <summary>
        /// 버튼 클릭 로직을 실행합니다.
        /// 이 메서드는 일반적으로 UI 시스템(예: Unity UI의 Button.onClick 이벤트)에 의해 호출되도록 설계됩니다.
        /// 버튼이 활성화(IsEnabled == true)되어 있고 ClickCommand가 할당되어 있다면, 해당 커맨드를 실행합니다.
        /// 파생 클래스에서 이 메서드를 재정의하여 특정 버튼 타입에 맞는 추가적인 클릭 동작을 구현할 수 있습니다.
        /// </summary>
        /// <param name="parameter">ClickCommand에 전달할 선택적 파라미터입니다.</param>
        public virtual void ExecuteClick(object parameter = null)
        {
            if (IsEnabled && ClickCommand != null)
            {
                ClickCommand.Execute(parameter); // 커맨드에 파라미터 전달
            }
        }

        /// <summary>
        /// OnStateChanged 이벤트를 외부에서 강제로 발생시킵니다.
        /// 여러 속성을 변경한 후 한 번에 UI 업데이트를 트리거하거나,
        /// 내부 상태 변경이 속성 변경을 통하지 않고 발생했을 때 유용합니다.
        /// </summary>
        /// <example>
        /// <code>
        /// public void UpdateButtonAppearance(string newText, string newIcon)
        /// {
        ///     _text = newText; // 직접 필드 값 변경 (setter의 OnStateChanged 호출 안됨)
        ///     _iconSpritePath = newIcon; // 직접 필드 값 변경
        ///     NotifyStateChanged(); // 수동으로 상태 변경 알림
        /// }
        /// </code>
        /// </example>
        public void NotifyStateChanged()
        {
            OnStateChanged?.Invoke();
        }

        /// <summary>
        /// 이 버튼 모델에 연결된 모든 이벤트 핸들러를 정리(구독 해제)합니다.
        /// 주로 View가 파괴되거나 UI가 재생성될 때 호출되어 메모리 누수를 방지합니다.
        /// 파생 클래스에서는 이 메서드를 재정의하여 해당 클래스에 특화된 이벤트를 추가로 정리해야 합니다.
        /// </summary>
        public virtual void ClearEventHandlers()
        {
            OnStateChanged = null;
        }
    }
}