import { isValid, Node, Quat, sp, sys, systemEvent, SystemEvent, tween, UIOpacity, UITransform, v3, Vec3, view } from "cc";
import { constants } from "../game/data/constants";
import { resManager } from "../game/manager/resManager";

export const cocosUtil = {

    addHand(attachNode: Node, parent: Node, cb?: Function) {
        resManager.instance.loadAsset(constants.bundles.common.name, constants.bundles.common.spine.shouzhi, sp.SkeletonData, () => { }, (err, skeletonData) => {
            if (err) {
                return;
            }
            let handNode = new Node();
            let handSkeleton = handNode.addComponent(sp.Skeleton);
            handSkeleton.skeletonData = skeletonData;
            handSkeleton.setAnimation(0, "dianji", true);
            handSkeleton.premultipliedAlpha = false;
            handNode.parent = parent;

            let pos = cocosUtil.convertToWorldSpace(attachNode, true);
            pos = cocosUtil.convertToNodeSpace(handNode, pos);
            handNode.setPosition(pos);
            if (cb) {
                cb(handNode);
            }
        });
    },

    tweenBlink(node: Node, time?: number) {
        if (!time) {
            time = 0.5;
        }
        tween(node.getComponent(UIOpacity)).to(time, {
            opacity: 0
        }).to(time, {
            opacity: 255
        }).union().repeatForever().start();
    },

    tweenRotate(node: Node, time?: number) {
        if (!time) {
            time = 2;
        }
        let quat = new Quat();
        let angle = 360;
        Quat.fromEuler(quat, 0, 0, angle);
        tween(node).by(time, { rotation: quat }, {
            easing: "linear",
            onUpdate: (target: Node, ratio: number) => {
                let da = angle * ratio;
                Quat.fromEuler(quat, 0, 0, da);
                target.setRotation(quat);
            }
        }).repeatForever().start();
    },

    tweenUpDown(node: Node, dy?: number, time?: number) {
        if (!dy) {
            dy = 10;
        }
        if (!time) {
            time = 1;
        }
        let pos1 = node.getPosition();
        pos1.y += dy;
        let pos2 = node.getPosition();
        tween(node).to(time, {
            position: pos1
        }).to(time, {
            position: pos2
        }).union().repeatForever().start();
    },

    tweenFadeOut(node: Node, time?: number, cb?: Function) {
        if (!time) {
            time = 1.5;
        }
        tween(node.getComponent(UIOpacity)).to(time, {
            opacity: 0
        }).call(() => {
            if (cb) {
                cb();
            }
        }).start();
    },

    /**
     * 放大缩小呼吸效果
     * @param node 节点
     * @param time 缩放时长，单位：秒
     * @param scale 缩放大小
     */
    tweenScaleBreath(node: Node, time?: number, scale?: number) {
        if (!time) {
            time = 0.4;
        }
        if (!scale) {
            scale = 1.2;
        }

        tween(node).to(
            time, {
            scale: v3(scale, scale, 1)
        }
        ).to(
            time, {
            scale: v3(1, 1, 1)
        }
        ).union().repeatForever().start();
    },

    /**
     * 间接性晃动效果
     * @param node 节点
     * @param time 时长，单位：秒
     * @param rotation 旋转角度，单位：度数
     * @param delayTime 中间暂停时长，单位：秒
     */
    tweenShake(node: Node, time?: number, rotation?: number, delayTime?: number) {
        if (!time) {
            time = 0.2;
        }
        if (!rotation) {
            rotation = 6;
        }
        if (delayTime == undefined) {
            delayTime = time * 5;
        }

        let quat1: Quat = new Quat();
        Quat.fromEuler(quat1, 0, 0, rotation);

        let quat2: Quat = new Quat();
        Quat.fromEuler(quat2, 0, 0, -rotation);

        let quat3: Quat = new Quat();
        Quat.fromEuler(quat3, 0, 0, 0);

        tween(node).to(time, {
            rotation: quat1
        }).to(time * 2, {
            rotation: quat2
        }).to(time, {
            rotation: quat3
        }).delay(delayTime).union().repeatForever().start();

    },

    /**
     * 判断节点是否可用
     * @param node 节点对象 
     */
    isNodeValid(node: Node) {
        if (!node || !isValid(node)) {
            return false;
        }
        return true;
    },

    isAndroid() {
        return sys.platform === sys.Platform.ANDROID;
    },

    isDesktopBrowser() {
        return sys.platform === sys.Platform.DESKTOP_BROWSER;
    },

    isIos() {
        return sys.platform === sys.Platform.IOS;
    },

    isWechatGame() {
        return sys.platform === sys.Platform.WECHAT_GAME;
    },

    addKeyDownListener(cb, sender) {
        systemEvent.on(SystemEvent.EventType.KEY_DOWN, cb, sender);
    },

    init() {
        // 设计分辨率
        this.designSize = view.getDesignResolutionSize();
        // 实际屏幕分辨率
        this.frameSize = view.getFrameSize();
        // 实际屏幕安全区域，{x: 0, y: 0, width: 766.6256157635468, height: 1660}
        // 是以左下角为原点，以设计分辨率为单位的，并且是遵循高度为适配原则后的尺寸
        this.safeAreaRect = sys.getSafeAreaRect();

        // 计算出顶部刘海屏高度
        this.safeAreaMarginTop = this.designSize.height - this.safeAreaRect.height;
        if (this.safeAreaMarginTop < 0) {
            this.safeAreaMarginTop = 0;
        }

        this.intiScreenAdapterWidthScale();
        this.initScreenBgAdapterWidthScale();
    },


    // UI适配，以高度为适配原则，按照满宽度显示计算，如果宽度不够显示，要乘以这个缩放比例
    intiScreenAdapterWidthScale() {
        let fh = this.frameSize.height;
        let fw = this.frameSize.width;

        let scale = fh / this.designSize.height;
        let adapterWidth = this.designSize.width * scale;
        let retScale = 1;
        if (adapterWidth > fw) {
            // 屏幕不够显示，有些交互UI会丢失，要进行缩小
            retScale = fw / adapterWidth;
        }

        // if (this.safeAreaMarginTop > 0) {
        //     // cocos内部以高度为适配策略，但是如果有刘海屏，要额外再缩放一点
        //     let subScale = this.safeAreaMarginTop / this.designSize.height;
        //     retScale -= subScale;
        // }

        this.screenAdapterScale = retScale;
    },
    getScreenAdapterScale() {
        if (!this.screenAdapterScale) {
            this.screenAdapterScale = 1;
        }
        return this.screenAdapterScale;
    },

    // 背景图适配，跟上面的UI适配，刚好相反，超出的屏幕不管，屏幕没显示满，要放大
    initScreenBgAdapterWidthScale() {
        let fh = this.frameSize.height;
        let fw = this.frameSize.width;
        let scale = fh / this.designSize.height;
        let adapterWidth = this.designSize.width * scale;
        let retScale = 1;
        if (adapterWidth < fw) {
            // 屏幕没显示满，会有黑边，要进行放大
            retScale = fw / adapterWidth;
        }

        // if (this.safeAreaMarginTop > 0) {
        //     // 额外增加放大值，使得背景图铺满包括刘海在内的整个屏幕
        //     let addScale = this.safeAreaMarginTop / this.designSize.height;
        //     retScale += addScale;
        // }

        this.screenBgAdapterScale = retScale;
    },
    getScreenBgAdapterScale() {
        if (!this.screenBgAdapterScale) {
            this.screenBgAdapterScale = 1;
        }
        return this.screenBgAdapterScale;
    },

    /**
     * 将node坐标转换为世界坐标
     * @param node 
     * @param isCenter 是否强制是node的中心点坐标
     */
    convertToWorldSpace(node: Node, isCenter?: boolean) {
        let transform = node.parent.getComponent(UITransform);

        let pos = node.getPosition();
        if (isCenter) {
            let tf = node.getComponent(UITransform);
            pos.x = pos.x + (0.5 - tf.anchorX) * tf.width;
            pos.y = pos.y + (0.5 - tf.anchorY) * tf.height;
        }

        return transform.convertToWorldSpaceAR(pos);
    },

    /**
     * 获得以node父节点锚点位置为原点的坐标系下的坐标
     * @param node 注意，是同坐标下的节点
     * @param pos 世界坐标
     */
    convertToNodeSpace(node: Node, pos: Vec3) {
        let transform = node.parent.getComponent(UITransform);

        return transform.convertToNodeSpaceAR(pos);
    },

    setPositionX(node: Node, x: number) {
        let pos = node.getPosition();
        pos.x = x;
        node.setPosition(pos);
    },

    setPositionY(node: Node, y: number) {
        let pos = node.getPosition();
        pos.y = y;
        node.setPosition(pos);
    },

}

