import { _decorator, Button, Component, easing, EventHandler, EventTouch, js, Node, Tween, tween, UITransform, Vec2, Vec3 } from 'cc';
import { Utils } from '../../utils/Utils';
import { Logger } from '../../extend/Logger';
import { uiMgr } from '../manager/UIManager';
import { eventEmitter } from '../event/EventEmitter';
import { initAutoBindings } from '../../extend/AutoBind';
import { Constants } from '../../data/Constants';
import { audioMgr } from '../manager/AudioManager';
const { ccclass, property } = _decorator;

@ccclass('BaseExp')
export class BaseExp extends Component {
    //事件数组
    private events:any[] = [];
    //是否允许点击空白关闭页面，默认true
    public closeOnBlank: boolean = true;
    //是否有出场放大的动画 默认true
    private _hasAnim: boolean = true;
    public set hasAnim(value: boolean) {
        if(value){
           this.showAnim();
        }
        this._hasAnim = value;
    }
    private oScale: Vec3 = Vec3.ZERO;
    private uiBG: Node = null;

    public onLoad() {
        this.events = [];
        //加入按钮点击
        this._addClickEvent(this.node);
        //自动绑定属性
        initAutoBindings(this);
        //监听节点点击事件
        this.node.on(Node.EventType.TOUCH_END, this.onNodeTouchEnd, this);
        //背景视图
        this.uiBG = this.node.getChildByName("UI");
        if(this.uiBG){
           this.oScale = this.uiBG.scale.clone();        
        }
    }

    /**
     * 展示加载缓动动画
     */
    public showAnim(){
        if(this.uiBG && this._hasAnim){
            Tween.stopAllByTarget(this.uiBG);
            this.uiBG.scale = new Vec3(0.95,0.95,0.95);
            let scale: Vec3 = this.oScale;
            tween(this.uiBG)
            .to(0.1, {scale: new Vec3(0.02 + scale.x,0.02 + scale.y,0.02 + scale.z)},{easing: easing.backOut})
            .to(0.1, {scale: new Vec3(scale.x - 0.02,scale.y - 0.02,scale.z - 0.02)},{easing: easing.backOut})
            .call(() => {
                this.uiBG.scale = this.oScale;
            }).start();
        }
    }

    /**
     * 节点触摸结束事件处理
     * @param event 触摸事件
     */
    private onNodeTouchEnd(event: EventTouch) {
        const uiBG = this.node.getChildByName("UI");
        if (!uiBG || !this.closeOnBlank)return;
        let trans: UITransform = this.node.getComponent(UITransform);
        const location = event.getUILocation();
        let pos = trans.convertToNodeSpaceAR(new Vec3(location.x,location.y));
        if(!uiBG.getComponent(UITransform).getBoundingBox().contains(new Vec2(pos.x,pos.y))){
            this.close();
        }
    }

    /**
     * 关闭页面
     * @param cb 关闭页面的回调
     */
    private close(cb?: Function){
        let pagePath: string = this.node["_uiPath"];
        if(!Utils.isNull(pagePath)){
            uiMgr.hide(pagePath,cb);
        }else{
            Logger.log(`请检查该: ${this.node.name}页面路径信息，不存在`);
        }
    }

    /**
     * 点击事件
     * @param event 事件
     * @param customEventData 数据
     */
    public onBtnClicked(event:EventTouch, customEventData:any) {
        audioMgr.playOneShot(Constants.audios.click);
        let btnName = event.target.name;
        if(btnName === 'close_btn'){
           this.close();
        }
    }

    /**
     * 是否允许添加
     * @param node 添加的节点
     */
    private _isSkipNode(node: Node): boolean {
        if(this.node == node) {
           return false;
        }
        let b = node.getComponent(BaseExp);
        if (b) //Logger.log("跳过", b.name)
        return b != null;
    }

    /**
     * 加入点击事件
     * @param node 加入点击的节点
     */
    private _addClickEvent(node: Node) {
        if (this._isSkipNode(node)) return;
        for (let i = 0; i < node.children.length; i++) {
            let n:Node = node.children[i];
            if(this._isSkipNode(n)) continue;
            if(n.getComponent(Button)) {
               this.addClickEvent(n, this.node, js.getClassName(this), "onBtnClicked", n);
            }
            this._addClickEvent(n);
        }
    }

    /**
     * 加入按钮点击事件
     * @param node 点击的节点
     * @param target 点击的对象
     * @param component 组建的类名
     * @param handler 处理的具柄
     * @param customEventData 传递的数据
     */
    private addClickEvent(node, target, component, handler, customEventData) {
        let eventHandler = new EventHandler()
        eventHandler.target = target;
        eventHandler.component = component;
        eventHandler.handler = handler;               
        if(customEventData){
           eventHandler.customEventData = customEventData;
        }
        let clickEvents = node.getComponent(Button).clickEvents;
        if (clickEvents.length > 0) {
            Logger.log(`${node.name}按钮已经存在绑定，跳过自动绑定`);
            return;
        }
        clickEvents.push(eventHandler);
    }

    //销毁的时候注销所有的事件
    public onDestroy() {
        for(let i = 0; i < this.events.length; i++){
            eventEmitter.unregister(this, this.events[i]);
        }
    }

    //注册事件
    public register(type: any, cb: Function) {
        this.events.push(type);
        eventEmitter.register(this, type, cb);
    }

    //取消注册的时间
    public unregister(type: any) {
        eventEmitter.unregister(this, type);
    }

    //事件派发
    public dispatch(type: any, ...data: any[]) {
        eventEmitter.dispatch(type, ...data);
    }
}

