import { _decorator, Component, find, geometry, instantiate, Node, NodePool, PhysicsSystem, Prefab, randomRange, randomRangeInt, tween, Vec3 } from 'cc';
import { RoleCarColorsComponent } from '../Components/RoleCarColorsComponent';
import { CarColors, CarTypes, RoleNames, UINames } from '../CarColorsGlobalTypes';
import { CarColorsGlobalInstance } from '../CarColorsGlobalInstance';
import { CarCarColorsComponent } from '../Components/CarCarColorsComponent';
import { AudioManager, AudioClipNames } from '../../../ScriptFrame/Frame/AudioManager';
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 prefabList: Array<Prefab> = await Promise.all(CarColorsGlobalInstance.instance.bundleSysterm.loadRolePrefab())
        prefabList.forEach((prefab, index)=>{
            colors.forEach(color=>{
                const pool = new NodePool()
                this.rolePools.set(color, {pool, prefab})
                for(let i = 10; i--;){
                    const role = instantiate(prefab)
                    role.getComponent(RoleCarColorsComponent).color = CarColors[color]
                    pool.put(role)
                }
            })
        })
    }

    showHomeRoles(){
        this.isGaming = false
        this.clearAll()
        const num = randomRangeInt(3,5)
        for(let i = num + 1;i--;){
            const rolesNode = find("Scene/Roles")
            const colorList = Object.keys(CarColors).filter(item => isNaN(Number(item)))
            const role = this.getRoleFromPool(CarColors[colorList[randomRangeInt(0,colorList.length)]])
            role.setScale(1.5,1.5,1.5)
            role.setPosition((i - num) * randomRange(2,2.5),0, 0)
            role.setRotationFromEuler(-20,0,0)
            rolesNode.addChild(role)
            role.active = true
            role.getComponent(RoleCarColorsComponent).playIdle()
            this.activeRole.set(role.uuid, role)
        }
    }

    initLevel(){
        AudioManager.instance.playBgm(AudioClipNames.bgm)
        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 = 10
            if (carComp.carType === CarTypes.Minivan){
                num = 6
            }else if (carComp.carType === CarTypes.Sedan){
                num = 4
            }
            num -= carComp.roleNum
            console.log(num)
            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)
        }
    }

    unlockParkPoint(){
        const points = find("Scene/Parkings").children
        if (points[5].name === "lock"){
            points[5].name = "empty"
            points[5].children[0].children[0].active = true
            points[5].children[0].children[1].active = false

            return
        }
        if (points[6].name === "lock"){
            points[6].name = "empty"
            points[6].children[0].children[0].active = true
            points[6].children[0].children[1].active = false

            return
        }
    }

    // 上客
    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){

            if (selectedCar.getComponent(CarCarColorsComponent).addRole(roleCom.node)){
                selectedCar.setParent(find("Scene/Levels"), true)
            }
            this.addRoleToLine()
        }else {
            
            // 游戏结束判定
            if (!isEmpty){
                this.isGaming = false
                CarColorsGlobalInstance.instance.uiSysterm.showUI(UINames.RevivePage)
            }
            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)
        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(-10, 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 > 0){
                    roleCom.playIdle()
                    roleCom.isIntarget = true
                    role.setRotationFromEuler(-40,0,0)
                    role.setPosition(0,0,0.2)
                    return
                }else if (!roleCom.isHorizon && pos.z > 0){
                    roleCom.playIdle()
                    roleCom.isHorizon = true
                    role.setRotationFromEuler(0,90,-30)
                    role.setPosition(-10,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)
    }
}


