// tslint:disable:only-arrow-functions
// tslint:disable:no-conditional-assignment
// tslint:disable:prefer-const
// tslint:disable:no-var-keyword
// tslint:disable:no-inferrable-types
import { Vector } from "./Vector";
import { degToRad, translateToLocalCor } from "./Const";
import { Tween } from "../tween/Tween";
import Body from "./Body";

export class Square extends Body {

    public type = "square"

    public view;

    _num;

    _x = 0;
    _y = 0;
    /**
     * 边长
     */
    public length;
    public _rotation = 0;       //顺时针为正方向,角度制

    //记录四条边的方向向量顺时针，从上边开始
    sideNormals = [
        new Vector(1, 0),
        new Vector(0, 1),
        new Vector(-1, 0),
        new Vector(0, -1)
    ];

    //记录四点的法向量，顺时针，从左上开始 未归一
    pointNormals = [
        new Vector(1, -1),
        new Vector(1, 1),
        new Vector(-1, 1),
        new Vector(-1, -1)
    ]

    // points = [
    //     new Vector(1, -1),
    //     new Vector(1, 1),
    //     new Vector(-1, 1),
    //     new Vector(-1, -1)
    // ]



    constructor(length, view) {
        super();
        this.length = length;
        this.view = view;
    }

    get rotation() {
        return this._rotation
    }
    set rotation(value) {
        if (this._rotation != value) {
            this._rotation = value;
            this.view.rotation = value;
            this.view.txt.rotation=-value;
            //计算四条边得方向向量,避免每帧计算   暂时不考虑优化90度
            var rad = value * degToRad;

            this.sideNormals[0] = new Vector(1, 0).rotate(rad);
            this.sideNormals[1] = new Vector(0, 1).rotate(rad);
            this.sideNormals[2] = new Vector(-1, 0).rotate(rad);
            this.sideNormals[3] = new Vector(0, -1).rotate(rad);
            this.pointNormals[0] = new Vector(1, -1).rotate(rad);
            this.pointNormals[1] = new Vector(1, 1).rotate(rad);
            this.pointNormals[2] = new Vector(-1, 1).rotate(rad);
            this.pointNormals[3] = new Vector(-1, -1).rotate(rad);
        }
    }

    get x() {
        return this._x;
    }

    set x(value) {
        if (this._x != value) {
            this._x = value;
            this.view.x = value;
        }
    }

    get y() {
        return this._y;
    }

    set y(value) {
        if (this._y != value) {
            this._y = value;
            this.view.y = value;
        }
    }

    get num() {
        return this._num;
    }

    set num(value) {
        if (this._num != value) {
            this._num = value;
            this.view.txt.text = value||4 + "";
        }
    }
    //新增，矫正偏移
    get _viewx(){
        return this.view.x;//+this.view.anchorX;
    }
    get _viewy(){
        return this.view.y;//+this.view.anchorY;
    }


    //碰撞，先转换球坐标到局部   在四个点时考虑要不要预先计算四个点的坐标，通过xyr  set时确定；
    collideBall(ball) {
        var returnP = translateToLocalCor({ x: ball._viewx, y: ball._viewy }, this.view);
        //正方形左上角点
        var ox = - this.length / 2;
        var oy = ox;
        var nearestX = Math.max(ox, Math.min(returnP.x, ox + this.length));
        var nearestY = Math.max(oy, Math.min(returnP.y, oy + this.length));

        var deltaX = returnP.x - nearestX;
        var deltaY = returnP.y - nearestY;
        //碰撞   则根据速度插值给上一帧的碰撞法向量   考虑是否直接按速度大小进行插值，还是用分量
        if (deltaX * deltaX + deltaY * deltaY < ball.radius * ball.radius) {
            var velocity = ball.velocity.clone().rotate(-this._rotation * degToRad);
            var deta = Math.floor(velocity.length() / ball.radius) + 5    //deta就是插值数量,如为0，则直接取上一帧的法向量
            var speedX = velocity.x / (deta + 1);
            var speedY = velocity.y / (deta + 1);
            for (var i = 0; i <= deta; i++) {
                var normal = this.nearestCollideNormal({ x: returnP.x - speedX * (i + 1), y: returnP.y - speedY * (i + 1) }, ball, deta + 1, i + 1)
                if (normal) {
                    return normal
                }
            }
            //    return false;   //意味着碰撞
        }
        //未碰撞
        else {
            return false
        }
    }

    private nearestCollideNormal(position, ball, deta, i) {
        var ox = - this.length / 2;
        var oy = ox;
        var nearestX = Math.max(ox, Math.min(position.x, ox + this.length));
        var nearestY = Math.max(oy, Math.min(position.y, oy + this.length));
        var deltaX = position.x - nearestX;
        var deltaY = position.y - nearestY;
        if (deltaX * deltaX + deltaY * deltaY < ball.radius * ball.radius) {
            return false;
        } else {
            //直接更改球的位置为最接近碰撞的位置
            ball.view.x -= ball.velocity.x / deta * i;
            ball.view.y -= ball.velocity.y / deta * i;
            //左边
            if (nearestX == ox) {
                if (nearestY == oy) {
                    return this.pointNormals[0];
                }
                else if (nearestY == oy + this.length) {
                    return this.pointNormals[3];
                } else {
                    return this.sideNormals[3];
                }
            }
            //右边
            else if (nearestX == ox + this.length) {
                if (nearestY == oy) {
                    return this.pointNormals[1];
                }
                else if (nearestY == oy + this.length) {
                    return this.pointNormals[2];
                } else {
                    return this.sideNormals[1];
                }
            }
            //中间
            else {
                if (nearestY < 0) {
                    return this.sideNormals[0];
                } else {
                    return this.sideNormals[2];
                }
            }
        }
    }


    public shake() {
        var startx = -this.view.bg.anchorX;
        var starty = -this.view.bg.anchorY;
        this.view.bg.x = startx;
        this.view.bg.y = starty;
        Tween.to(this.view.bg, 1, {
            x:  startx+5,
            y:  starty+5,
            yoyo: 3,
            useFrame: true,
            onComplete: function () {
            }

        })
    }
}