import ConfigManager from "../../../engines/configs/ConfigManager";
import MathUtils from "../../../engines/utils/MathUtils";
import GameController from "./GameController";


/**
 * 圆内多边形
 */
export default class InCirclePolygon
{   
    /**
     * 中心点
     */
    center:cc.Vec3;
    /**
     * 中心点的高度
     */
    centerHeight:number;

    /**
     * 外角
     */
    outAngle:number;

    /**
     * 内角角度
     */
    private angle:number;

    /**
     * 内角数量
     */
    private count:number;
    /**
     * 边长
     */
    private side:number;
    private helfSide:number;

    /**
     * 长度
     */
    private length:number;

    /**
     * X轴的数据范围
     */
    minX:number;
    maxX:number;

    /**
     * 物理数据
     */
    private physicsData:number[][];
    private physicsTileSize:cc.Vec2;
    private physicsSize:cc.Vec2;

    /**
     * 多边形数据
     */
    private polygon:cc.Node;
    private polygonTiles:cc.Rect[];
    polygonTileAngles:number[];

    /**
     * 圆内多边形
     * @param side    边长 
     * @param count   内角数量
     * @param length  长度
     * @param circumradius 外接圆半径
     * @param physicsData  物理数据
     */
    constructor(polygon:cc.Node){
        this.polygon=polygon;
        this.side=GameController.single.levelConfig.side;
        this.helfSide=this.side*0.5;
        this.count=GameController.single.levelConfig.count;
        this.angle=360/this.count;
        this.length=GameController.single.levelConfig.length;


        //物理数据
        let jsonAsset:cc.JsonAsset=ConfigManager.single.GetConfig(GameController.single.levelConfig.physicsConfig);
        let config:any=jsonAsset.json;

        //展开
        this.minX=0
        this.maxX=this.count*this.side;
        this.InitPolygonTiles();

        //计算中心点高度
        this.center=new cc.Vec3();
        this.centerHeight=MathUtils.InCirclePolygonCentre(this.side,this.angle);
        
        this.physicsData=config.data;
        //物理块大小
        this.physicsTileSize=new cc.Vec2();
        this.physicsTileSize.x=this.centerHeight*Math.tanh(MathUtils.angle2Radian(config.angleInterval*0.5))*2;
        this.physicsTileSize.y=config.tileHeight;

        //物理块索引空间大小
        this.physicsSize=new cc.Vec2();
        this.physicsSize.x=this.physicsData[0].length;
        this.physicsSize.y=this.physicsData.length;

        this.outAngle=180-(90-this.angle*0.5)*2;
    }

    private InitPolygonTiles():void{
        //多边形举行
        this.polygonTiles=[];
        this.polygonTileAngles=[];
        let tile:cc.Rect;
        for (let index = 0; index < this.count; index++) {
            tile=new cc.Rect();
            tile.x=index*this.side;
            tile.y=0;
            tile.width=this.side;
            tile.height=this.length;
            this.polygonTiles.push(tile);
            this.polygonTileAngles.push(index*-this.angle);
        }

        let lastTile:cc.Rect=this.polygonTiles[this.polygonTiles.length-1];
        tile=new cc.Rect();
        tile.x=-this.side;
        tile.y=0;
        tile.width=lastTile.width;
        tile.height=lastTile.height;
        this.polygonTiles.unshift(tile);

        tile=new cc.Rect();
        tile.x=lastTile.x+lastTile.width;
        tile.y=0;
        tile.width=this.polygonTiles[0].width;
        tile.height=this.polygonTiles[0].height;
        this.polygonTiles.push(tile);
        
        let leftAngle:number=this.angle;
        let rightAngle:number=-360;
        this.polygonTileAngles.unshift(leftAngle);
        this.polygonTileAngles.push(rightAngle);
    }
    
    /**
     * 重置
     */
    Reset():void{
        this.SetAngle(0);
        this.SetCenter(0,this.centerHeight,0);
    }

    /**
     * 测试并返回相交的内容
     * @param rect 
     * @param out
     */
    PolygonIntersects(rect:cc.Rect,out:number[]):void{
        out.length=0;
        let tile:cc.Rect;
        for (let index = 0; index < this.polygonTiles.length; index++) {
            tile=this.polygonTiles[index];
            if(rect.intersects(tile)){
                out.push(index);
            }
        }
    }

    /**
     * 获取多边形块
     * @param index 
     */
    GetPolygonTile(index:number):cc.Rect{
        return this.polygonTiles[index];
    }

    /**
     * 获取多边形块角度
     * @param index 
     */
    GetPolygonTileAngle(index:number):number{
        return this.polygonTileAngles[index];
    }


    Update(dt:number):void{
        this.polygon.x=this.center.x;
        this.polygon.y=this.center.y;
        this.polygon.z=this.center.z;
        // cc.log("多边形位置：",this.polygon.x,this.polygon.y,this.polygon.z);
    }

    /**
     * 获取物理状态
     * @param px 
     * @param py
     */
    GetPhysicsState(x:number,y:number):number{
        if(x<0||x>=this.physicsSize.x){
            return 0;
        }
        if(y<0||y>=this.physicsSize.y){
            return;
        }
        return this.physicsData[y][x];
    }

    /**
     * 逻辑坐标转物理坐标
     * @param logicX 
     * @param logicY 
     * @param out 
     */
    GetPhysicsPos(logicX:number,logicY:number,out:{x:number,y:number}):void{
        out.x=this.Pixel2Physics(logicX,this.physicsTileSize.x);
        out.y=this.Pixel2Physics(logicY,this.physicsTileSize.y);
    }

    public Pixel2Physics(value:number,baseValue:number):number{
        let fValue:number=value/baseValue;
        let iValue:number=Math.floor(value/baseValue);
        if(fValue-iValue>0){
            iValue+=1;
        }
        iValue-=1;
        if(iValue<0){
            iValue=0;
        }
        return iValue;
    }

    /**
     * 设置角度
     * @param value 
     */
    SetAngle(value:number):void{
        this.polygon.angle=value;
    }

    /**
     * 设置中心点
     * @param value 
     */
    SetCenter(x:number,y:number,z:number){
        this.center.x=x;
        this.center.y=y;
        this.center.z=z;
    }

    private __tempVec3:cc.Vec3=new cc.Vec3();
    private __tempVec3_1:cc.Vec3=new cc.Vec3();
    private __tempMat4:cc.Mat4=new cc.Mat4();
    private __tempQuat:cc.Quat=new cc.Quat();
    /**
     * 旋转中心点
     * @param angle 
     * @param point 
     * @param origin 
     */
    RotationCenter(angle:number,point:cc.Vec3,origin:cc.Vec3):void{
        let red:number=MathUtils.angle2Radian(angle);
        let srcDir:cc.Vec3=this.__tempVec3;
        cc.Vec3.subtract(srcDir,point,origin);

        let q:cc.Quat=this.__tempQuat;
        cc.Quat.fromAxisAngle(q,new cc.Vec3(0,0,1),red);
        let m:cc.Mat4=this.__tempMat4;
        cc.Mat4.fromRTS(m,q,cc.Vec3.ZERO,cc.Vec3.ONE);
        let newDir:cc.Vec3=this.__tempVec3_1;
        cc.Vec3.transformMat4(newDir,srcDir,m);
        origin.add(newDir,this.center);
    }
}