import {
    _decorator, Collider, CollisionEventType, ICollisionEvent,
    Input,
    input,
    instantiate,
    Node, ParticleSystem, PhysicsGroup, PhysicsSystem,
    PointToPointConstraint,
    Prefab,
    primitives,
    RigidBody, tween,
    v3,
    Vec3,
} from "cc";
import Scene from "db://assets/Module/Scene";
import { ImprovedNoise } from "../../Utils/ImprovedNoise";
import { Wall } from "./Wall";
import { sleep } from "../../Utils/Utils";

const {ccclass, property} = _decorator;

@ccclass("MainGame")
export class MainGame extends Scene {
    static bundle: string = "MainGame";
    static skin: string = "MainGame";
    static group: string[] = ["MainGame"];

    @property(Node) linkPoint: Node = null;
    @property(Node) line: Node = null;

    @property(Node) player: Node = null;
    playerBody: RigidBody = null;
    playerConstraint: PointToPointConstraint = null;


    @property(Node) initWall: Node = null;

    @property(Prefab) wallPrefab: Prefab = null;

    @property(Node) crushNode: Node = null;

    isTouch = false;

    pNoise: ImprovedNoise = new ImprovedNoise();

    wallArr: Node[] = [];

    onLoad() {
        this.playerBody = this.player.getComponent(RigidBody);
        this.playerConstraint = this.linkPoint.getComponent(PointToPointConstraint);

        input.on(Input.EventType.TOUCH_START, this.onTouchStart, this);
        input.on(Input.EventType.TOUCH_MOVE, this.onTouchMove, this);
        input.on(Input.EventType.TOUCH_END, this.onTouchEnd, this);
        input.on(Input.EventType.TOUCH_CANCEL, this.onTouchEnd, this);

        this.player.getComponent(Collider)
            .on("onCollisionEnter", this.onPlayerCollision, this);

        this.wallArr[4] = this.initWall;
        for (let i = 0; i <= 3; i++) {
            this.wallArr[i] = this.createCube(4 - i);
        }

        for (let i = 5; i <= 10; i++) {
            this.wallArr[i] = this.createCube();
        }
    }

    async start() {

    }

    isOver: boolean = false;

    async gameOver(success) {
        this.isOver = true;


        await sleep(3);



    }

    onPlayerCollision(event: ICollisionEvent) {

        if (this.isOver) return;


        const {otherCollider, selfCollider} = event;

        const otherGroup = otherCollider.getGroup();

        if (otherGroup === PhysicsSystem.PhysicsGroup['Wall']) {
            // 死了

            this.playerBody.enabled = false;
            this.player.destroy();

            this.crushNode.setPosition(this.player.position);
            this.crushNode.getComponent(ParticleSystem)
                .play();

            this.gameOver(false);
        }

    }

    createCube(z = this.wallArr[this.wallArr.length - 1].position.z - 1) {
        const newGroup = instantiate(this.wallPrefab);
        this.node.addChild(newGroup);
        newGroup.setPosition(v3(0, Math.random(), z));
        return newGroup;
    }

    onTouchStart(event: any) {
        if (this.isOver) return;

        this.isTouch = true;

        this.line.active = true;

        const pPos = this.player.position;
        const targetZ = pPos.z - 0.5;
        const index = this.wallArr[0].position.z - Math.round(targetZ);
        const y = this.wallArr[index].getComponent(Wall).topY;

        const linkPos = v3(0, y, targetZ);
        this.linkPoint.setPosition(linkPos);

        // 计算角度
        const dir = Vec3.subtract(new Vec3(), linkPos, pPos);
        const angle = Math.atan(dir.z / dir.y) * 180 / Math.PI;
        this.player.setRotationFromEuler(angle, 0, 0);

        // 重新设置连接点
        const constraintY = Vec3.distance(pPos, linkPos);
        this.playerConstraint.pivotB = v3(0, constraintY, 0);
        this.playerConstraint.enabled = true;

        this.playerBody.setLinearVelocity(v3());
        this.playerBody.setAngularVelocity(v3());
    }

    onTouchMove(event: any) {

    }

    onTouchEnd(event: any) {
        if (this.isOver) return;

        this.isTouch = false;
        this.line.active = false;
        this.playerConstraint.enabled = false;
    }

    checkFrame = 0;

    checkWall() {
        this.checkFrame = 0;
        const pPos = this.player.position;
        const index = this.wallArr[0].position.z - Math.round(pPos.z);

        const createCount = index - 4;
        for (let i = 0; i < createCount; i++) {
            const wall = this.wallArr.shift();
            wall.setPosition(0, Math.random(), this.wallArr[this.wallArr.length - 1].position.z - 1);
            this.wallArr.push(wall);
        }

    }

    update(dt: number) {

        this.checkFrame++;
        // 检测是否需要生成墙
        if (this.checkFrame >= 20) {
            this.checkWall();
        }

        if (this.isTouch) {
            const lineScale = Vec3.distance(this.player.position, this.linkPoint.position);
            this.line.setScale(1, lineScale / 2, 1);

            this.playerBody.applyForce(v3(0, 0, -10));
        }

    }


}
