import {
    _decorator, assetManager,
    Component,
    find,
    geometry,
    instantiate,
    Node,
    NodePool,
    PhysicsSystem,
    Prefab,
    randomRange,
    randomRangeInt,
    Vec3
} from 'cc';
import { RoleCarColorsComponent } from '../Components/RoleCarColorsComponent';
import { CarCarColorsComponent } from '../Components/CarCarColorsComponent';
import { AudioClipName, AudioMgr } from "db://assets/core/base/AudioMgr";
import { showPanel } from "db://assets/core/Module/UIFast";
import { ReviewPanel } from "db://assets/Scripts/Panels/ReviewPanel";
import { CarColors } from "db://assets/Scripts/Scenes/MainGame/CarColorsGlobalTypes";
import { CarColorsGlobalInstance } from "db://assets/Scripts/Scenes/MainGame/CarColorsGlobalInstance";
import { MainGame } from "db://assets/Scripts/Scenes/MainGame/MainGame";
import gameStore from "db://assets/Scripts/store/gameStore";

const { ccclass, property } = _decorator;

@ccclass('RoleCarColorsSysterm')
export class RoleCarColorsSysterm extends Component {
    // 对象池
    rolePools: Map<string, { pool: NodePool, prefab: Prefab[] }> = new Map()
    activeRole: Map<string, Node> = new Map()

    isGaming: boolean = false

    async loadRolePrefabs() {
        const colors = Object.keys(CarColors).filter(item => isNaN(Number(item)))
        const rolePrefab = await new Promise<Prefab>((resolve) => {
            assetManager.getBundle("MainGame")
                .load(`prefab/character_man`, Prefab, (err, prefab: Prefab) => {
                    if (err) {
                        resolve(null);
                        return
                    }
                    resolve(prefab);
                })
        })
        const girlPrefab = await new Promise<Prefab>((resolve) => {
            assetManager.getBundle("MainGame")
                .load(`prefab/character_girl`, Prefab, (err, prefab: Prefab) => {
                    if (err) {
                        resolve(null);
                        return
                    }
                    resolve(prefab);
                })
        })
        colors.forEach(color => {
            const pool = new NodePool()
            this.rolePools.set(color, { pool, prefab: [rolePrefab, girlPrefab] })
            for (let i = 5; i--;) {
                const role = instantiate(rolePrefab);
                role.getComponent(RoleCarColorsComponent).color = CarColors[color]
                pool.put(role)

                const gril = instantiate(girlPrefab);
                gril.getComponent(RoleCarColorsComponent).color = CarColors[color]
                pool.put(gril)
            }
        })
    }

    initLevel() {
        AudioMgr.ins.play(AudioClipName.bgm, { loop: true });
        this.clearAll()
        this.addRoleToLine()
        this.scheduleOnce(() => {
            this.isGaming = true
        }, 1)
    }

    refreshRoleLine(){
        const points = find("Scene/Parkings").children
        let cars: Array<Node> = []
        for(let i = points.length; i--;){
            if (points[i].name === "inuse" && points[i].children.length === 2){
                cars.push(points[i].children[1])
            }
        }
        let colors: Array<CarColors> = []
        for(let i = cars.length; i--;){
            const car = cars[i]
            const carComp = car.getComponent(CarCarColorsComponent)
            let num = carComp.sitNum;
            num -= carComp.roleNum
            for(;num--;){
                // console.log(num)
                colors.push(carComp.carColor)
            }
        }
        console.log(colors.length)
        const roles = find("Scene/Roles").children
        for(let i = 0;i < colors.length;i++){
            if (i >= roles.length){
                break
            }
            const roleCom = roles[i].getComponent(RoleCarColorsComponent)
            if (roleCom.color !== colors[i]){
                const colorIndex = CarColorsGlobalInstance.instance.carSysterm.carSeats.lastIndexOf(colors[i])

                // 存量未找到，从队列中找
                if (colorIndex === -1){
                    for (let j = roles.length;j--;){
                        if (roles[j].getComponent(RoleCarColorsComponent).color === colors[i]){
                            roles[j].getComponent(RoleCarColorsComponent).color = roleCom.color
                            break
                        }
                    }
                } else{
                    CarColorsGlobalInstance.instance.carSysterm.carSeats[colorIndex] = roleCom.color
                }
                roleCom.color = colors[i]
            }
        }


        this.isGaming = true
    }

    addRoleToLine() {

        const rolesNode = find("Scene/Roles")
        for (let i = CarColorsGlobalInstance.instance.carSysterm.carSeats.length; i--;) {
            if (rolesNode.children.length > 30) {
                break
            }
            const color = CarColorsGlobalInstance.instance.carSysterm.carSeats.pop()
            const role = this.getRoleFromPool(color)
            role.getComponent(RoleCarColorsComponent).playIdle()
            role.getComponent(RoleCarColorsComponent).isHorizon = false
            role.getComponent(RoleCarColorsComponent).isIntarget = false
            role.setScale(1, 1, 1)
            role.active = false
            this.activeRole.set(role.uuid, role)

            let insetIndex = rolesNode.children.length - randomRangeInt(1, 6)
            if (insetIndex < 0) {
                insetIndex = 0
            }
            rolesNode.insertChild(role, insetIndex)
        }
    }

    // 上客
    moveToCar() {
        const roles = [...find("Scene/Roles").children]
        if (roles.length === 0) return
        const roleCom = roles[0].getComponent(RoleCarColorsComponent)
        if (!roleCom.isIntarget) return
        const points = find("Scene/Parkings").children
        let cars: Array<Node> = []
        let isEmpty = false
        for (let i = points.length; i--;) {
            if (points[i].name === "inuse" && points[i].children.length === 2) {
                cars.push(points[i].children[1])
                continue
            }

            if (points[i].name === "empty") {
                isEmpty = true
                continue
            }
            if (points[i].name === "inuse" && points[i].children.length === 1) {
                isEmpty = true
                continue
            }
        }

        if (cars.length === 0) {
            // console.log("没车了")
            return
        }

        //
        let selectedCar: Node = null
        for (let i = cars.length; i--;) {
            const car = cars[i]
            const carComp = car.getComponent(CarCarColorsComponent)
            // 颜色相同
            if (carComp.carColor === roleCom.color) {
                if (selectedCar === null) {
                    selectedCar = car
                    continue
                }
                if (selectedCar.getComponent(CarCarColorsComponent).roleNum === 0) {
                    selectedCar = car
                }
            }
        }

        // 匹配的车
        if (selectedCar !== null) {

            const isFull = selectedCar.getComponent(CarCarColorsComponent).addRole(roleCom.node)
            if (isFull) {
                selectedCar.setParent(find("Scene/Levels"), true)
            }
            this.addRoleToLine()
        } else {

            // 游戏结束判定
            if (!isEmpty) {
                this.isGaming = false
                const lockIndex = MainGame.ins.getLockPoints();
                if (!lockIndex) {
                    gameStore.submit(false);
                } else {
                    showPanel(ReviewPanel);
                }
            }
            return
        }
    }


    clearOne(roleCom: RoleCarColorsComponent) {
        this.activeRole.delete(roleCom.node.uuid)
        const poolItem = this.rolePools.get(CarColors[roleCom.color])
        poolItem.pool.put(roleCom.node)
    }

    // 清除所有人
    clearAll() {
        this.activeRole.forEach(role => {
            role.removeFromParent()
            const poolItem = this.rolePools.get(CarColors[role.getComponent(RoleCarColorsComponent).color])
            poolItem.pool.put(role)
        })
        this.activeRole.clear()
    }

    // 从对象池获取
    getRoleFromPool(color: CarColors): Node {
        const poolItem = this.rolePools.get(CarColors[color])
        if (poolItem.pool.size() > 0) {
            return poolItem.pool.get()
        }
        const role = instantiate(poolItem.prefab[randomRangeInt(0, poolItem.prefab.length)])
        role.getComponent(RoleCarColorsComponent).color = color
        return role
    }

    // 更新角色位置
    updateRolePos(dt: number) {
        find("Scene/Roles").children.forEach((role, index) => {
            if (role.getComponent(RoleCarColorsComponent).status === "sit") return

            if (index < 18) {
                const roleCom = role.getComponent(RoleCarColorsComponent)
                if (!role.active) {
                    role.active = true
                    roleCom.playIdle()
                    roleCom.isHorizon = false
                    role.setRotationFromEuler(-40, 0, 0)
                    role.setPosition(4.5, 0, -6 - index * 2)
                    return
                }

                let pos = new Vec3()
                role.getPosition(pos)
                let wpos = role.getWorldPosition()
                let forward = new Vec3(0, 0, -1)
                if (roleCom.isHorizon) {
                    forward = new Vec3(1, 0, 0)
                }

                const add = forward.clone().multiplyScalar(dt * -20)
                let distance = add.length()
                if (distance < 1) {
                    distance = 1
                }

                let mask = 1 << 6
                let ray = new geometry.Ray(wpos.x, wpos.y, wpos.z, add.x, 0, add.z)
                if (PhysicsSystem.instance.raycastClosest(ray, mask, distance, true)) {
                    roleCom.playIdle()
                    return
                }

                pos.add(add)

                // 到达终点判定
                if (roleCom.isHorizon && pos.x < -6) {
                    roleCom.playIdle()
                    roleCom.isIntarget = true
                    role.setRotationFromEuler(-40, 0, 0)
                    role.setPosition(-6, 0, 0.2)
                    return
                } else if (!roleCom.isHorizon && pos.z > 0) {
                    roleCom.playIdle()
                    roleCom.isHorizon = true
                    role.setRotationFromEuler(0, -90, 30)
                    role.setPosition(4.5, 0, 0)
                    return
                }
                if (role.getComponent(RoleCarColorsComponent).status === "sit") return
                roleCom.playWalk()
                role.setPosition(pos)
            } else {
                role.active = false
            }
        })

        this.moveToCar()
    }

    protected lateUpdate(dt: number): void {
        if (!this.isGaming) return
        this.updateRolePos(dt)
    }
}


