import { LevelManager } from "./LevelManager";
import { ResourcesManager, baseroaddata, fixedroaddata, thingsdata, buildtype } from "./ResourcesManager";
import PoolManager from "./PoolManager";
import Vector3 = Laya.Vector3;
import { Runner, ColliderLay } from "./Runner";
import Sprite3D = Laya.Sprite3D;
import { GameManager, GameState } from "./GameManager";
import { Player } from "./Player";
import CameraManager from "./CameraManager";
import { GameUtils } from "../../GameUtils/GameUtils";
import { Level, roadthings, Stage, RunnerRoad } from "./LevelData";
import { AImanager } from "./AIManager";
import Vector4 = Laya.Vector4;
import { PlayerAccount, AccountUser } from "../Network/PlayerAccount";

export class Road
{
    constructor(_id:number,_data:RunnerRoad,_offestY:number,_offestZ:number,_parent:Sprite3D,_textureid:number,_roadcolor:number)
    {
        this.id = _id;
        this.parent = _parent;
        var roadpos = new Vector3(3.6-(_id*1.8),_offestY - _data.high_change,_offestZ);
        this.Long = _data.long;
        this.CreatModel(_data.long*RunnerRoad.lengthrate,roadpos,_textureid,_roadcolor);
        this.CreateThings(_data.things,_data.position,_data.thing_hight,roadpos);
    }
    id:number;
    sprite:Laya.Sprite3D;
    things:roadthings[] = [];
    builds:Sprite3D[] = [];
    startpos:Vector3;
    parent:Sprite3D;
    Long:number;
    jumpHight:number = 0;

    CreatModel(_size:number,_pos:Vector3,_texture:number,__roadcolor:number)
    {
        this.startpos = _pos;
        if(_size != 0)
        {
            var sprite = PoolManager.Instance.CreatMeshSprite3D(ResourcesManager.Instance.bsroadassets[baseroaddata.ZhiRoad],"");
            this.sprite = sprite;
            this.sprite.transform.position = _pos;

            var meshchild = sprite.getChildAt(0).getChildAt(0).getChildAt(0) as Laya.MeshSprite3D;
            var materail = meshchild.meshRenderer.material as Laya.BlinnPhongMaterial;
            var tes = ResourcesManager.Instance.planetextures;
            materail.albedoTexture = tes[_texture];
            var colors = ScenceManager.randomcolor;
            materail.albedoColor = colors[__roadcolor - 1];

            FixedRoad.ForNodeSetColliderInThis(this.sprite,ColliderLay.Plane);
            this.sprite.transform.localScaleZ = _size;
            this.parent.addChild(this.sprite);
        }
    }

    CreateThings(_things:roadthings[],_poss:string[],_hights:number[],_pos:Vector3)
    {
        for(var i = 0;i < _things.length;i++)
        {
            //var curposZ = Number(_poss[i])*3;
            var curposZ = Number(_poss[i]);
            var curpos = new Vector3(_pos.x,_pos.y,_pos.z + curposZ - 1);
            var res = ResourcesManager.Instance.tsroadassets;

            if(id == thingsdata.PlateTrampoline)
            {
                // curpos = new Vector3(curpos.x,curpos.y - this.jumpHight,curpos.z);
                // this.jumpHight += 0.5;
                var highchange = _hights.length == _poss.length?_hights[i]:0;
                curpos = new Vector3(curpos.x,curpos.y - highchange,curpos.z);
                if(this.jumpHight < _hights[i])this.jumpHight = _hights[i];
            }

            var id = _things[i].id;
            
            if(id == 0 || !res[id])continue;

            if((this.id == thingsdata.Box || this.id == thingsdata.Box1 || this.id == thingsdata.Box2))
            {
                var things = Sprite3D.instantiate(ResourcesManager.Instance.tsroadassets[this.id]);
                
                var box = things.getChildByName("Box").getComponent(Laya.PhysicsCollider) as Laya.PhysicsCollider;
                box.collisionGroup = ColliderLay.things;
            }
            else
            {
                var things = PoolManager.Instance.CreatMeshSprite3D(res[id],"");
                FixedRoad.ForNodeSetColliderInThis(things,ColliderLay.things);
            }

            var thing = new roadthings(_things[i].id.toString());
            thing.buffertime = _things[i].buffertime;
            thing.effect = _things[i].effect;
            thing.model = _things[i].model;
            thing.pos = curpos;
            thing.type = _things[i].type;
            thing.sprite = things;
            thing.length = curposZ;
            this.things.push(thing);

            things.transform.position = curpos;
            ScenceManager.Instance.GameScence.addChild(things);
        }
    }

    Resset()
    {
        var things = this.things;
        for(var k = 0;k < things.length;k++)
        {
            var thing = things[k];
            thing.Resset();
        }
    }

    Clear()
    {
        if(this.sprite)
        {
            this.sprite.active = true;
            PoolManager.Instance.RecoverMeshSprite3D(this.sprite);
        }
        var things = this.things;
        for(var k = 0;k < things.length;k++)
        {
            var thing = things[k];
            thing.Clear();
        }
        // var builds = LevelManager.Instance.curLevel.builds;
        // for(var k = 0;k < builds.length;k++)
        // {
        //     var build = builds[k];
        //     PoolManager.Instance.RecoverMeshSprite3D(build);
        // }
    }

    SetActive(_open:boolean)
    {
        if(this.sprite)
        {
            this.sprite.active = _open;
        }
        var things = this.things;
        for(var k = 0;k < things.length;k++)
        {
            var thing = things[k];
            thing.sprite.active = _open;
        }
        // var builds = LevelManager.Instance.curLevel.builds;
        // for(var k = 0;k < builds.length;k++)
        // {
        //     var build = builds[k];
        //     build.active = _open;
        // }
    }
}

export class FixedRoad
{
    constructor(_id:number,_pos:Vector3 = new Vector3(0,0,0),_parent:Laya.Sprite3D = null)
    {
        this.id = _id;
        var roadasset;
        var sprite = PoolManager.Instance.CreatMeshSprite3D(ResourcesManager.Instance.fxroadassets[_id],"");
        this.sprite = sprite;
        this.sprite.transform.position = _pos;
        if(sprite.getChildByName("endpoint"))this.endSprite = sprite.getChildByName("endpoint") as Sprite3D;

        FixedRoad.ForNodeSetColliderInThis(this.sprite,ColliderLay.Plane);

        if(_parent)
        {
            _parent.addChild(this.sprite);
        }
        else
        {
            ScenceManager.Instance.GameScence.addChild(this.sprite);
        }
    }
    id:number;
    sprite:Laya.Sprite3D;
    endSprite:Sprite3D;

    //遍历节点设置碰撞体属性
    static ForNodeSetColliderInThis(_node:Laya.Node,lay:number)
    {
        var childNumber = _node.numChildren;

        for(var i = 0;i < childNumber;i ++)
        {
            var eChildNumber = _node.getChildAt(i).numChildren;
            if(eChildNumber > 0)
            {
                this.ForNodeSetColliderInThis(_node.getChildAt(i),lay);
            }

            var PhysicsCollider = _node.getChildAt(i).getComponent(Laya.PhysicsCollider) as Laya.PhysicsCollider;
            if(PhysicsCollider)
            {
                this.SetCollider(PhysicsCollider,lay);
            }
        }
    }

    //设置碰撞体属性
    static SetCollider(Collider:Laya.PhysicsCollider,_lay:number)
    {
        Collider.collisionGroup = _lay;
    }
}

export class ScenceManager 
{
    static Instance:ScenceManager
    public GameScence:Laya.Scene3D;
    public GameCamera:Laya.Camera;
    public GameLight:Laya.DirectionLight;
    //public m_effect_JS:Sprite3D;
    constructor(_scence:Laya.Scene3D)
    {
        ScenceManager.Instance = this;
        this.GameScence = _scence;
        this.GameScence.physicsSimulation.maxSubSteps = 15;
        this.GameScence.physicsSimulation.fixedTimeStep = 1/60;

        this.GameScence.enableFog = true;
        this.GameScence.fogStart = 25;
        this.GameScence.fogRange = 35;
        this.GameScence.fogColor = new Vector3(0.5803922,0.8431373,1);
        this.Init();
    }

    static randomcolor = 
    [
        new Vector4(145*1.0/255,1,101*1.0/255,1),
        new Vector4(162*1.0/255,56*1.0/255,1,1),
        new Vector4(1,150*1.0/255,38*1.0/255,1),
    ]

    LevelRoads:Road[] = [];
    
    Init()
    {
        this.GameCamera = this.GameScence.getChildByName("Main Camera") as Laya.Camera;
        this.GameCamera.transform.position = new Vector3(0,0.6,8.5);
        this.GameCamera.transform.rotationEuler = new Vector3(-5,180,0);
        this.GameCamera.clearColor = new Vector4(0.5803922,0.8431373,1,1);

        this.GameLight = this.GameScence.getChildByName("Directional Light") as Laya.DirectionLight;

        this.GameCamera.addComponent(CameraManager);

        var startroad = this.GameScence.getChildByName("PlateStart");
        FixedRoad.ForNodeSetColliderInThis(startroad,ColliderLay.Plane);

        var FalconMesh = this.GameScence.getChildByName("FalconMesh") as Sprite3D;
        ResourcesManager.Instance.FalconMesh = FalconMesh;
        FalconMesh.removeSelf();

        var crown = this.GameScence.getChildByName("crown") as Sprite3D;
        ResourcesManager.Instance.crown = crown;
        crown.removeSelf();

        //ResourcesManager.Instance.InitRoleAsset();
    }


    CreatLevelScene(_frist = false)
    {
        ScenceManager.Instance.GameLight.transform.rotationEuler = new Laya.Vector3(-50,-150,0);
        var level = LevelManager.Instance.curLevel;
        this.CreatLevelRoads(level);
        this.CreatPlayer(level,_frist);
        AImanager.Instance.CreatAi();
        GameManager.Instance.ChangeState(GameState.Idle);
    }

    CreatLevelRoads(_level:Level)
    {
        var curY = -5.5;
        var rd1pos = new Vector3(0,curY,20);
        _level.ramproad = new FixedRoad(fixedroaddata.Ramps,rd1pos);

        var startpos = _level.ramproad.endSprite.transform.position;
        var offesthight = startpos.y - 6;

        for(var i = 0;i < _level.stages.length;i++)
        {
            var stagedata = _level.stages[i];
            
            //console.log(startpos.z);
            offesthight -= stagedata.StageHight;
            if((i - 1)>-1)
            {
                var sss = _level.stages[i - 1].stagejumphight;
                offesthight -= sss;
            }
            var offestz = 0;
            var maxlength = 0;
            var maxhight = 0;
            stagedata.sprite = new Sprite3D();
            stagedata.sprite.name = "stagesprite"+ i;
            ScenceManager.Instance.GameScence.addChild(stagedata.sprite);
            var longs = 0;
            for(var j = 0;j < stagedata.roadsdata.length;j++)
            {
                var start = stagedata.roadsdata[j].start;
                offestz = startpos.z + start;
                
                var road = new Road(j,stagedata.roadsdata[j],offesthight,offestz,stagedata.sprite,_level.pic,_level.colour);
                stagedata.roads.push(road);

                if(road.jumpHight > stagedata.stagejumphight)stagedata.stagejumphight = road.jumpHight;
                
                if(i > 1)
                {
                    road.SetActive(false);
                }

                var thingsLength = road.things.length > 0?road.things[road.things.length - 1].length:0;
                longs = stagedata.roadsdata[j].long == 0?thingsLength:stagedata.roadsdata[j].long;

                if(offestz + longs > maxlength)maxlength = offestz + longs;
                if(offesthight - (stagedata.roadsdata[j].high_change + road.jumpHight) < maxhight)maxhight = offesthight - (stagedata.roadsdata[j].high_change + road.jumpHight);
                
            }

            stagedata.startz = offestz;
            stagedata.endz = maxlength;
            
            stagedata.starty = offesthight;
            stagedata.endy = maxhight;
            startpos = new Vector3(0,maxhight,maxlength);
            // console.log(i + ":"+stagedata.starty);
            // console.log(i + ":"+stagedata.endy);
            this.CreatBuilds(stagedata);
        }

        _level.getRoadPoint();

        var endpos = new Vector3(0,startpos.y -5.5,startpos.z + 2);
        var endroad = new FixedRoad(fixedroaddata.PlateFinish,endpos);
        _level.endroadsprite = endroad.sprite;
        var wincollider = endroad.sprite.getChildByName("Win").getComponent(Laya.PhysicsCollider) as Laya.PhysicsCollider;
        wincollider.collisionGroup = ColliderLay.things;
        _level.endroadsprite.active = false;
    }

    starthideindex = 1;

    SortRoad(a:Road,b:Road):number
    {
        if(a.Long > b.Long)
        {
            return -1;
        }
        else
        {
            return 1;
        }
    }

    CreatPlayer(_level:Level,_frist:boolean)
    {
        var playerid = Number(PlayerAccount.CurrentAccount.CurAccountData.GetUser(AccountUser.equip_hero));
        var player = ResourcesManager.Instance.roleassets[playerid].getChildAt(0) as Sprite3D;
        var playermodel = PoolManager.Instance.CreatMeshSprite3D(player,"");
        var startpoint = new Vector3(0,0,10);
        playermodel.transform.position = startpoint;
        
        var hatid = Number(PlayerAccount.CurrentAccount.CurAccountData.GetUser(AccountUser.equip_hat));
        if(hatid > 0)
        {
            var hat = ResourcesManager.Instance.hatasset[hatid];
            var hatmodel = PoolManager.Instance.CreatMeshSprite3D(hat,"");
            var head = playermodel.getChildAt(0).getChildAt(0) as Laya.Sprite3D;
            head.addChild(hatmodel);
            hatmodel.transform.localPosition = new Laya.Vector3(0.1,0,0);
            hatmodel.transform.localRotationEuler = new Laya.Vector3(0,90,0);
        }

        var cbid = Number(PlayerAccount.CurrentAccount.CurAccountData.GetUser(AccountUser.equip_hat));
        if(cbid > 0)
        {
            var cb = ResourcesManager.Instance.cbasset[cbid];
            var cbmodel = PoolManager.Instance.CreatMeshSprite3D(cb,"");
            var back = playermodel.getChildAt(0).getChildAt(1) as Laya.Sprite3D;
            back.addChild(cbmodel);
            cbmodel.transform.localPosition = new Laya.Vector3(-0.06,-0.06,0);
            cbmodel.transform.localRotationEuler = new Laya.Vector3(-25,90,180);
        }

        this.GameScence.addChild(playermodel);
        
        if(_frist)
        {
            new Player(playermodel);
        }
        else
        {
            Player.Instance.Reset(playermodel);
        }
    }


    buildsnum = 10;
    hightnum = 2;
    CreatBuilds(_stage:Stage)
    {
        var offestz = 0;
        var offestY = 0;
        //var startpos = _stage.sprite.transform.position;
        var offesthight = _stage.endy - 30;
        var length = _stage.endz - _stage.startz;
        var hight = 0;
        this.buildsnum = 1;
        var level = LevelManager.Instance.curLevel;
        for(var i = 0;i < this.buildsnum;i++)
        {
            offestz += (length/this.buildsnum);
            offestY = hight;

            var build = PoolManager.Instance.CreatMeshSprite3D(ResourcesManager.Instance.buildsassets[level.buildid],"");
            var pos = new Vector3(12,offesthight - offestY,_stage.startz + offestz);
            build.transform.position = pos;
            ScenceManager.Instance.GameScence.addChild(build);
            _stage.builds.push(build);

            var build2 = PoolManager.Instance.CreatMeshSprite3D(ResourcesManager.Instance.buildsassets[level.buildid],"");
            var pos = new Vector3(-12,offesthight - offestY,_stage.startz + offestz);
            build2.transform.position = pos;
            ScenceManager.Instance.GameScence.addChild(build2);
            _stage.builds.push(build2);

            if(i > 0)
            {
                build.active = false;
                build2.active = false;
            }
        }
    }

}