import {
    _decorator,
    BoxCollider,
    Camera,
    Component,
    EventTouch,
    find,
    geometry,
    Input,
    instantiate,
    Label,
    Node,
    NodePool,
    PhysicsSystem,
    Quat,
    RigidBody,
    Tween,
    tween,
    Vec3
} from 'cc';
import { CarCarColorsComponent } from './Components/CarCarColorsComponent';
import { PlatformManager } from '../../../ScriptFrame/Frame/platformManager';
import { showPanel, showToast } from "db://assets/core/Module/UIFast";
import { AudioClipName, AudioMgr } from "db://assets/core/base/AudioMgr";
import { UnlockPanel } from "db://assets/Scripts/Panels/UnlockPanel";
import { CarColorsGlobalInstance } from "db://assets/Scripts/Scenes/MainGame/CarColorsGlobalInstance";
import gameStore from "db://assets/Scripts/store/gameStore";
import { MainGame } from "db://assets/Scripts/Scenes/MainGame/MainGame";

const { ccclass, property } = _decorator;

@ccclass('GamePage')
export class GamePage extends Component {

    isAnimateObstacle: boolean = false;

    isAnimateHelicopter: boolean = false;
    isChooseHelicopterTarget: boolean = false;

    smokePool: NodePool = new NodePool();

    start(): void {
        this.node.on(Input.EventType.TOUCH_START, this.touchStart, this);
        this.isAnimateObstacle = false;
        if (this.smokePool.size() === 0) {
            const smokeTemp = find("Scene/Smoke");
            this.smokePool.put(instantiate(smokeTemp));
            this.smokePool.put(instantiate(smokeTemp));
            this.smokePool.put(instantiate(smokeTemp));
        }
    }

    getSmoke(): Node {
        if (this.smokePool.size() > 0) {
            return this.smokePool.get();
        }
        return instantiate(find("Scene/Smoke"))
    }

    putSmoke(smoke: Node) {
        smoke.removeFromParent();
        smoke.active = false;
        this.smokePool.put(smoke);
    }

    getEmptyParkPoint(): Node {
        const points = find("Scene/Parkings").children;
        for (let i = 0; i < points.length; i++) {
            if (points[i].name === "empty") {
                return points[i];
            }
        }
        return null;
    }

    touchStart(event: EventTouch) {
        if (this.isAnimateObstacle) return;
        if (this.isAnimateHelicopter) return;
        let ray = new geometry.Ray();
        find("Main Camera").getComponent(Camera).screenPointToRay(event.getLocationX(), event.getLocationY(), ray);
        // 以下参数可选
        let mask = 1 << 2; // 停车位分组
        let maxDistance = 100000;
        let queryTrigger = true;

        // 点中停车位
        if (!this.isChooseHelicopterTarget && PhysicsSystem.instance.raycastClosest(ray, mask, maxDistance, queryTrigger)) {
            const parkPoint = PhysicsSystem.instance.raycastClosestResult.collider.node.parent.parent;
            const parkIndex = parkPoint.getSiblingIndex();

            if (parkIndex === 4) {
                MainGame.ins.shareUnlock();
            } else if (parkIndex === 5) {
                MainGame.ins.videoUnlock1();
            } else if (parkIndex === 6) {
                MainGame.ins.videoUnlock2();
            }
            return;
        }

        mask = 1 << 1; // 汽车分组
        // 点中汽车
        if (PhysicsSystem.instance.raycastClosest(ray, mask, maxDistance, queryTrigger)) {
            PlatformManager.instance.startVibrate()
            const car = PhysicsSystem.instance.raycastClosestResult.collider.node

            // 直升机挪车到VIP位置
            if (this.isChooseHelicopterTarget) {
                this.node.getChildByName("chooseTip").active = false
                this.isChooseHelicopterTarget = false
                this.isAnimateHelicopter = true
                this.helicopterTween(car)
                return
            }
            const halfLen = car.getComponent(CarCarColorsComponent).halfLen
            const pos = car.getWorldPosition()
            const forward = car.forward.clone().multiplyScalar(-1)
            // 检测前方第一个碰撞体
            ray = new geometry.Ray(pos.x, pos.y, pos.z, forward.x, forward.y, forward.z)
            mask = (1 << 1) + (1 << 4)
            if (PhysicsSystem.instance.raycastClosest(ray, mask, maxDistance, queryTrigger)) {
                const collider = PhysicsSystem.instance.raycastClosestResult.collider
                const carMovePos = pos.clone().add(forward.clone().multiplyScalar(PhysicsSystem.instance.raycastClosestResult.distance - halfLen))
                // 碰到车
                if (collider.getGroup() === 1 << 1) {
                    this.isAnimateObstacle = true
                    tween(car)
                        .to(0.1, { worldPosition: carMovePos })
                        // .delay(0.1)
                        .to(0.1, { worldPosition: pos })
                        .call(() => {
                            this.isAnimateObstacle = false
                        })
                        .start()

                    // 被撞的车
                    const colliderCar = collider.node
                    // 旋转轴
                    const rotAxis = car.forward.clone()
                    Vec3.rotateY(rotAxis, rotAxis, new Vec3(0, 0, 0), 1.57)
                    // 被撞车辆原本的旋转四元数
                    const wRotation = colliderCar.getWorldRotation().clone()
                    // 计算被撞车辆倾斜后旋转四元数
                    const targetRotation = new Quat()
                    Quat.rotateAround(targetRotation, wRotation.clone(), rotAxis.clone(), -0.5)

                    // 播放摇晃动画
                    tween(colliderCar)
                        .delay(0.1)
                        .to(0.05, {
                            worldRotation: targetRotation
                        })
                        .to(0.05, {
                            worldRotation: wRotation
                        })
                        .start()
                    AudioMgr.ins.playOneShot(AudioClipName.crash);
                }
                // 碰到路
                else {
                    // 获取停车位
                    const point = this.getEmptyParkPoint()
                    if (point === null) {
                        showToast("当前车位已满");
                        return
                    }

                    const hitPoint = PhysicsSystem.instance.raycastClosestResult.hitPoint.clone()
                    car.getComponent(BoxCollider).enabled = false
                    car.getComponent(RigidBody).enabled = false
                    const smoke = this.getSmoke()
                    car.addChild(smoke)
                    smoke.active = true
                    let tweenCar: Tween<Node> = tween(car)
                    // 顶部导航
                    if (collider.node.name === "physicRoodTop") {
                        this.hitPointTween(car, point, tweenCar, hitPoint)
                        this.topRoadTween(car, point, tweenCar)
                    }
                    // 左边导航
                    else if (collider.node.name === "physicRoodLeft") {
                        const targetPoint = find("Scene/physicRoodTop/leftPoint")
                        this.hitPointTween(car, targetPoint, tweenCar, hitPoint)
                        this.leftRoadTween(car, tweenCar)
                        this.topRoadTween(car, point, tweenCar)
                    }
                    // 右边导航
                    else if (collider.node.name === "physicRoodRight") {
                        const targetPoint = find("Scene/physicRoodTop/rightPoint")
                        this.hitPointTween(car, targetPoint, tweenCar, hitPoint)
                        this.rightRoadTween(car, tweenCar)
                        this.topRoadTween(car, point, tweenCar,)
                    }
                    // 底部导航
                    else if (collider.node.name === "physicRoodBottom") {
                        if (pos.x > 0) {
                            const targetPoint = find("Scene/physicRoodBottom/rightPoint")
                            this.hitPointTween(car, targetPoint, tweenCar, hitPoint)
                            this.bottomRoadTween(car, targetPoint, tweenCar)
                            this.rightRoadTween(car, tweenCar)

                        } else {
                            const targetPoint = find("Scene/physicRoodBottom/leftPoint")
                            this.hitPointTween(car, targetPoint, tweenCar, hitPoint)
                            this.bottomRoadTween(car, targetPoint, tweenCar)
                            this.leftRoadTween(car, tweenCar)
                        }
                        this.topRoadTween(car, point, tweenCar,)
                    }
                    point.name = "inuse"
                    tweenCar.call(() => {
                        car.setParent(point, true)
                        // CarColorsGlobalInstance.instance.roleSysterm.moveToCar()
                        car.getChildByName("arrow").active = false
                        car.children[0].children[0].children[0].active = false
                        car.setScale(1.15, 1.15, 1.15)
                        this.putSmoke(smoke)
                    }).start();
                }
            }
        }
    }

    helicopterTween(car: Node) {
        const parkPoint = find("Scene/Parkings").children[7]
        parkPoint.name = "inuse"
        parkPoint.children[0].children[0].active = true
        parkPoint.children[0].children[1].active = false
        const helicopter = find("Scene/helicopterPoint/helicopter");
        helicopter.active = true
        const carPos = car.getWorldPosition()
        helicopter.forward = carPos.clone().subtract(helicopter.getWorldPosition()).normalize()

        AudioMgr.ins.play(AudioClipName.helico, { loop: true })
        tween(helicopter)
            .to(1, { worldPosition: carPos.clone().add3f(0, 3, 0) })
            .call(() => {
                car.setParent(helicopter, true)
                car.setRotationFromEuler(0, 180, 0)
                const forward = helicopter.forward.clone()
                const targetforward = parkPoint.getWorldPosition().subtract(helicopter.getWorldPosition())
                tween(forward).to(0.5, { x: targetforward.x, y: targetforward.y, z: targetforward.z }, {
                    onUpdate: () => {
                        helicopter.forward = forward
                    }
                }).start()
            })
            .delay(0.5)
            .to(1, { worldPosition: parkPoint.children[0].getWorldPosition().add3f(0, 3, 0) })
            .call(() => {
                car.forward = new Vec3(-1.2, 0, 2)
                car.setParent(parkPoint, true)
                CarColorsGlobalInstance.instance.roleSysterm.isGaming = true
                this.isAnimateHelicopter = false
                car.getChildByName("arrow").active = false
                car.children[0].children[0].children[0].active = false
                car.setScale(1.15, 1.15, 1.15)

                const forward = helicopter.forward.clone()
                const targetforward = helicopter.getPosition().multiplyScalar(-1)
                tween(forward).to(0.2, { x: targetforward.x, y: targetforward.x, z: targetforward.x }, {
                    onUpdate: () => {
                        helicopter.forward = forward
                    }
                }).start()
            })
            .to(1, { position: new Vec3(0, 0, 0) })
            .call(() => {
                AudioMgr.ins.play(AudioClipName.bgm, { loop: true });
                helicopter.active = false
            })
            .start();
    }

    // 导航到碰撞点
    hitPointTween(car: Node, targetPoint: Node, tweenCar: Tween<Node>, hitPoint: Vec3 = null) {
        const pointForward: Vec3 = hitPoint.clone().subtract(targetPoint.getWorldPosition()).normalize()
        tweenCar
            .to(0.2, { worldPosition: hitPoint })
            .call(() => {
                AudioMgr.ins.playOneShot(AudioClipName.brake);
                const carforward = car.forward.clone()
                tween(carforward).to(0.1, { x: pointForward.x, y: pointForward.y, z: pointForward.z }, {
                    onUpdate: () => {
                        car.forward = carforward
                    }
                }).start()
            })
            .delay(0.1)
    }

    // 顶部导航
    topRoadTween(car: Node, targetPoint: Node, tweenCar: Tween<Node>) {
        tweenCar
            .to(0.2, { worldPosition: targetPoint.getWorldPosition() })
            .call(() => {
                AudioMgr.ins.playOneShot(AudioClipName.brake);
                const carforward = car.forward.clone()
                tween(carforward).to(0.1, { x: 2, y: 0, z: 2 }, {
                    onUpdate: () => {
                        car.forward = carforward
                    }
                }).start()
            })
            .delay(0.1)
            .to(0.2, {
                worldPosition: targetPoint.children[0].getWorldPosition()
            })

    }

    // 左边导航
    leftRoadTween(car: Node, tweenCar: Tween<Node>) {
        const targetPoint = find("Scene/physicRoodTop/leftPoint")
        tweenCar
            .to(0.2, { worldPosition: targetPoint.getWorldPosition() })
            .call(() => {
                AudioMgr.ins.playOneShot(AudioClipName.brake);
                const carforward = car.forward.clone()
                tween(carforward).to(0.1, { x: -1, y: 0, z: 0 }, {
                    onUpdate: () => {
                        car.forward = carforward
                    }
                }).start()
            })
            .delay(0.1)

    }

    // 右边导航
    rightRoadTween(car: Node, tweenCar: Tween<Node>) {
        const targetPoint = find("Scene/physicRoodTop/rightPoint")
        tweenCar.to(0.2, {
            worldPosition: targetPoint.getWorldPosition()
        })
            .call(() => {
                AudioMgr.ins.playOneShot(AudioClipName.brake);
                const carforward = car.forward.clone()
                tween(carforward).to(0.1, { x: 1, y: 0, z: 0 }, {
                    onUpdate: () => {
                        car.forward = carforward
                    }
                }).start()
            })
            .delay(0.1)

    }

    // 底部导航
    bottomRoadTween(car: Node, targetPoint: Node, tweenCar: Tween<Node>) {
        tweenCar.to(0.2, {
            worldPosition: targetPoint.getWorldPosition()
        })
            .call(() => {
                AudioMgr.ins.playOneShot(AudioClipName.brake);
                const carforward = car.forward.clone()
                tween(carforward).to(0.1, { x: 0, y: 0, z: 1 }, {
                    onUpdate: () => {
                        car.forward = carforward
                    }
                }).start()
            })
            .delay(0.1)

    }
}


