import { Node, Component, Button } from 'cc';

/**
 * UI基类
 * 职责:
 * - 定义UI的基础接口和生命周期
 * - 管理UI根节点
 * - 提供显示/隐藏控制
 * 
 * 所有UI必须继承此类并实现onGetUrl方法
 */
export abstract class UIBase {
    /** UI根节点 */
    protected _node: Node | null = null;
    
    /** UI是否已加载 */
    protected _isLoaded: boolean = false;
    
    /** UI是否显示中 */
    protected _isShowing: boolean = false;
    
    /**
     * 获取UI资源路径 (必须重载)
     * @returns UI预制体路径
     * @example
     * onGetUrl(): string {
     *     return 'UI/Login/UILogin';
     * }
     */
    abstract onGetUrl(): string;
    
    /**
     * UI开始时调用 (可选重载)
     * 在UI预制体加载完成后调用
     * 可以在此方法中初始化UI数据、绑定事件等
     * @param params 传入的参数
     * @example
     * onStart(params?: any): void {
     *     console.log('UI初始化', params);
     *     // 绑定按钮事件
     *     this.bindEvents();
     * }
     */
    onStart?(params?: any): void | Promise<void>;
    
    /**
     * UI结束时调用 (可选重载)
     * 在UI被卸载前调用
     * 可以在此方法中清理资源、解绑事件等
     * @example
     * onEnd(): void {
     *     console.log('UI清理');
     *     // 解绑按钮事件
     *     this.unbindEvents();
     * }
     */
    onEnd?(): void;
    
    /**
     * UI更新 (可选重载)
     * 在每帧调用(仅当UI显示时)
     * @param dt 距离上一帧的时间(秒)
     * @example
     * onUpdate(dt: number): void {
     *     // 更新倒计时
     *     this.updateTimer(dt);
     * }
     */
    onUpdate?(dt: number): void;
    
    /**
     * 设置UI根节点
     * 由UIMgr在加载完成后调用
     * @param node UI根节点
     */
    setNode(node: Node): void {
        this._node = node;
        this._isLoaded = true;
    }
    
    /**
     * 获取UI根节点
     * @returns UI根节点,如果未加载则返回null
     */
    getNode(): Node | null {
        return this._node;
    }
    
    /**
     * 显示UI
     */
    show(): void {
        if (this._node) {
            this._node.active = true;
            this._isShowing = true;
        }
    }
    
    /**
     * 隐藏UI
     */
    hide(): void {
        if (this._node) {
            this._node.active = false;
            this._isShowing = false;
        }
    }
    
    /**
     * 检查UI是否显示中
     * @returns true表示正在显示,false表示已隐藏
     */
    isShowing(): boolean {
        return this._isShowing;
    }
    
    /**
     * 检查UI是否已加载
     * @returns true表示已加载,false表示未加载
     */
    isLoaded(): boolean {
        return this._isLoaded;
    }
    
    /**
     * 查找子节点并获取组件
     * @param path 节点路径,支持多层级查找(如: 'mid/input_account')
     * @param componentType 组件类型
     * @returns 组件实例,未找到则返回null
     * @example
     * const editBox = this.GetChild('mid/input_account', EditBox);
     * const button = this.GetChild('btn_login', Button);
     */
    protected GetChild<T extends Component>(path: string, componentType: { new(): T }): T | null {
        if (!this._node) {
            console.error('[UIBase] GetChild失败: UI根节点不存在');
            return null;
        }
        
        const childNode = this._node.getChildByPath(path);
        if (!childNode) {
            console.error(`[UIBase] GetChild失败: 未找到节点 ${path}`);
            return null;
        }
        
        const component = childNode.getComponent(componentType);
        if (!component) {
            console.error(`[UIBase] GetChild失败: 节点 ${path} 未挂载 ${componentType.name} 组件`);
            return null;
        }
        
        return component;
    }
    
    /**
     * 设置按钮点击事件
     * @param button Button组件或包含Button组件的Node
     * @param callback 点击回调函数
     * @param target 回调函数的this指向
     * @example
     * const btn = this.GetChild('btn_login', Button);
     * this.SetClick(btn, this.onLoginClick, this);
     */
    protected SetClick(button: Button | Node | null, callback: () => void, target?: any): void {
        if (!button) {
            console.error('[UIBase] SetClick失败: button为null');
            return;
        }
        
        let targetNode: Node | null = null;
        
        // 判断是Button组件还是Node
        if (button instanceof Button) {
            targetNode = button.node;
        } else if (button instanceof Node) {
            targetNode = button;
        }
        
        if (!targetNode) {
            console.error('[UIBase] SetClick失败: 无法获取目标节点');
            return;
        }
        
        // 绑定点击事件
        targetNode.on(Node.EventType.TOUCH_END, callback, target);
    }
}
