import BaseItem from "./BaseItem";
import getRotation from "./utils/getRotation";
import MovieClip from "./movieclip/MovieClip";
import LabelType from "../startScene/LabelType";

export default class EgretRender {
    _root: egret.Sprite;
    private _engine: Matter.Engine;
    constructor(root: egret.Sprite, engine: Matter.Engine) {
        this._root = root;
        this._engine = engine;
    }

    addBody(body: Matter.Body, display: egret.DisplayObject) {
        if (display) {
            body['display'] = display;
            this._root.addChildAt(display, 0);
        }
        return body;
    }

    remove(body: Matter.Body): any {
        this.removeBody(body);
        this.removeDisplay(body);
    }

    removeBody(body: Matter.Body): any {
        Matter.World.remove(this._engine.world, body);
    }

    removeDisplay(body: Matter.Body): any {
        const display: egret.DisplayObject = body['display'];
        if (display && display.parent)
            display.parent.removeChild(display);
    }

    run() {
        const bodies = Matter.Composite.allBodies(this._engine.world);
        // tslint:disable-next-line:prefer-for-of
        for (let i = 0; i < bodies.length; i++) {
            const body = bodies[i];
            const display = body['display'] as egret.DisplayObject;
            if (!display) continue;

            // 贴图与刚体位置的小数点后几位有点不一样，需要降低精度
            const x1 = Math.round(display.x)
            const x2 = Math.round(body.position.x)
            const y1 = Math.round(display.y)
            const y2 = Math.round(body.position.y)
            const distanceX = Math.abs(x1 - x2);
            const distanceY = Math.abs(y1 - y2);
            const precision = 1;//精度
            if (distanceX > precision || distanceY > precision) {
                if (display instanceof MovieClip) display.resume();
            } else {
                if (display instanceof MovieClip) display.pause();
            }
            display.x = body.position.x;
            display.y = body.position.y;
            if (display instanceof MovieClip) {
                if (display.lable == LabelType.Boom)
                    display.rotation = getRotation(body.angle);
            }
            else
            display.rotation = getRotation(body.angle);
        }
    }

    //快速方法
    rectangle(x: number, y: number, width: number, height: number, display: egret.DisplayObject, options?: Matter.IChamferableBodyDefinition) {
        const body = this.rectangleToRender(x, y, width, height, display, options);
        this.addBodyToWorld(body);
        return body;
    }

    circle(x: number, y: number, radius: number, display: egret.DisplayObject, options?: Matter.IChamferableBodyDefinition, maxSides?) {
        const body = this.circleToRender(x, y, radius, display, options, maxSides);
        this.addBodyToWorld(body);
        return body;
    }

    polygon(x: number, y: number, sides: number, radius: number, display: egret.DisplayObject, options?: Matter.IChamferableBodyDefinition) {
        const body = this.polygonToRender(x, y, sides, radius, display, options);
        this.addBodyToWorld(body);
        return body;
    }

    //工具方法
    private addBodyToWorld(body: Matter.Body) {
        Matter.World.add(this._engine.world, body);
        return body;
    }

    private rectangleToRender(x: number, y: number, width: number, height: number, display: egret.DisplayObject, options?: Matter.IChamferableBodyDefinition) {
        const body = Matter.Bodies.rectangle(x, y, width, height, options);
        this.addBody(body, display);
        return body;
    }

    private circleToRender(x: number, y: number, radius: number, display: egret.DisplayObject, options?: Matter.IChamferableBodyDefinition, maxSides?) {
        const body = Matter.Bodies.circle(x, y, radius, options, maxSides);
        this.addBody(body, display);
        return body;
    }


    private polygonToRender(x: number, y: number, sides: number, radius: number, display: egret.DisplayObject, options?: Matter.IChamferableBodyDefinition) {
        const body = Matter.Bodies.polygon(x, y, sides, radius, options);
        this.addBody(body, display);
        return body;
    }
}