import UILayer from "../Component/UILayer";
import MTimer from "../Global/MTimer";

export default class DebugMgr extends UILayer {
    public enabled: boolean = true;
    public enabledGraphic: boolean = true;
    private shapeMap = {};
    private graphicDebugLayer: engine.Container = null;
    private uiLayer: engine.Container = null;
    private log: engine.Label = null;
    public test: any = null;
    private labelFPS = new engine.Label();

    public onClick = () => { }

    constructor() {
        super();
        if (!this.enabled) return;
        //创建图形调试层
        this.graphicDebugLayer = new UILayer();
        this.addChild(this.graphicDebugLayer);
        //创建UI层
        this.uiLayer = new engine.Container();
        this.addChild(this.uiLayer);
        //创建帧率标签
        this.labelFPS.size = 30;
        this.labelFPS.fillColor = "rgba(255,255,255,1)";
        this.labelFPS.text = "0";
        this.labelFPS.x = 20;
        this.labelFPS.y = 20;
        this.uiLayer.addChild(this.labelFPS);


        /* this.log = new engine.Label("Log");
        this.log.horizontalCenter = 0;
        this.log.top = 50;
        this.log.textColor = 0xffffff;
        this.log.stroke = 0.5;
        this.log.size = 32;
        this.uiLayer.addChild(this.log); */
        //创建调试按钮
        /* let button = new engine.Label("调试");
        button.textColor = 0x000000;
        button.borderColor = 0x000000;
        button.border = true;
        button.top = 30;
        button.right = 50;
        this.uiLayer.addChild(button);
        button.onTap(this, () => {
            this.onClick();
        }); */
    }

    public setLog(msg: string) {
        if (!this.enabled) return;
        this.log.text = msg;
    }

    public drawRect(rect: engine.Rectangle, style: GraphicDebug.Style = { color: 0x00ff00, lineSize: 1 }) {
        if (!this.enabled || !this.enabledGraphic) return;
        let shape = new engine.Shape();
        shape.beginStroke(style.color);
        shape.drawRect(rect.x, rect.y, rect.width, rect.height);
        shape.endStroke();
        this.graphicDebugLayer.addChild(shape);
    }

    public drawCircle(x: number, y: number, radius: number, style: GraphicDebug.Style = { color: 0x00ff00, lineSize: 1 }) {
        if (!this.enabled || !this.enabledGraphic) return;

        let shape = new engine.Shape();
        shape.beginStroke(style.color);
        shape.drawCircle(x, y, radius);
        shape.endStroke();
        this.graphicDebugLayer.addChild(shape);
    }

    public drawLine(line: GraphicDebug.Line, style: GraphicDebug.Style = { color: 0x00ff00, lineSize: 1 }) {
        if (!this.enabled || !this.enabledGraphic) return;
        let shape = new engine.Shape();
        shape.beginStroke(style.color);
        shape.moveTo(line.startX, line.startY);
        shape.lineTo(line.endX, line.endY);
        shape.endStroke();
        this.graphicDebugLayer.addChild(shape);
    }

    public updateLine(key: string, line: GraphicDebug.Line, style: GraphicDebug.Style = { color: 0x00ff00, lineSize: 1 }) {
        if (!this.enabled || !this.enabledGraphic) return;
        let shape: engine.Shape = this.shapeMap[key];
        if (!shape) {
            shape = new engine.Shape();
            this.graphicDebugLayer.addChild(shape);
            this.shapeMap[key] = shape;
        }

        shape.clear();
        shape.beginStroke(style.color);
        shape.moveTo(line.startX, line.startY);
        shape.lineTo(line.endX, line.endY);
        shape.endStroke();
    }

    public updateRect(key: string, rect: engine.Rectangle, style: GraphicDebug.Style = { color: 0x00ff00, lineSize: 1 }) {
        if (!this.enabled || !this.enabledGraphic) return;
        let shape: engine.Shape = this.shapeMap[key];
        if (!shape) {
            shape = new engine.Shape();
            this.graphicDebugLayer.addChild(shape);
            this.shapeMap[key] = shape;
        }

        shape.clear();
        shape.beginStroke(style.color);
        shape.drawRect(rect.x, rect.y, rect.width, rect.height);
        shape.endStroke();
    }

    public updateCircle(key: string, x: number, y: number, radius: number, style: GraphicDebug.Style = { color: 0x00ff00, lineSize: 1 }) {
        if (!this.enabled || !this.enabledGraphic) return;
        let shape: engine.Shape = this.shapeMap[key];
        if (!shape) {
            shape = new engine.Shape();
            this.graphicDebugLayer.addChild(shape);
            this.shapeMap[key] = shape;
        }

        shape.clear();
        shape.beginStroke(style.color);
        shape.drawCircle(x, y, radius);
        shape.endStroke();
    }

    public clearShape(key: string) {
        if (!this.enabled || !this.enabledGraphic) return;
        let shape: engine.Shape = this.shapeMap[key];
        if (!shape) {
            return;
        }

        delete this.shapeMap[key];
        shape.dispose();
    }

    init(context: engine.Container) {
        context.addChild(this);
        MTimer.onFrame("DebugMgr", this.onUpdate, this);
    }

    private lastFrameData: { runTime: number, frameCount: number } = { runTime: 0, frameCount: 0 };
    private curFrameData: { runTime: number, frameCount: number } = { runTime: 0, frameCount: 0 };
    private resetTimer = 0;

    private onUpdate(dt: number) {
        this.curFrameData.runTime += dt;
        this.curFrameData.frameCount += 1;
        this.resetTimer += dt;

        let average = (this.curFrameData.runTime + this.lastFrameData.runTime) / (this.curFrameData.frameCount + this.lastFrameData.frameCount)


        if (this.resetTimer > 200) {
            this.labelFPS.text = Math.round(1000 / average).toString();
            this.lastFrameData.runTime = this.curFrameData.runTime;
            this.lastFrameData.frameCount = this.curFrameData.frameCount;
            this.curFrameData.runTime = 0;
            this.curFrameData.frameCount = 0;
            this.resetTimer = 0;
        }

    }

    private static _instance: DebugMgr = null;
    public static get instance(): DebugMgr {
        if (!this._instance) {
            this._instance = new DebugMgr();
        }

        return this._instance;
    }
}

export namespace GraphicDebug {
    export interface Style {
        color: number;
        lineSize: number;
    }
    export interface Line {
        startX: number;
        startY: number;
        endX: number;
        endY: number;
    }
}