import {SColor, SPainter, SPoint, SRect} from "@persagy-web/draw/lib";
import { SGraphItem } from "@persagy-web/graph/lib";
import { Door } from "@persagy-web/big/lib/types/floor/Door";
import { ItemColor, ItemOrder } from "@persagy-web/big/lib";
import { SMathUtil } from "@persagy-web/big/lib/utils/SMathUtil";

/**
 * 门item
 *
 * @author  郝建龙
 */
export class SDoorItem extends SGraphItem {
    /** 门数据 */
    data: Door;
    /** 门轮廓线坐标list  */
    private readonly pointArr: SPoint[] = [];
    /** 门长度 */
    private readonly r: number = 0;
    /** 角度  */
    private readonly ang: number = 0;
    /** 旋转点 */
    private readonly p: SPoint = new SPoint(0, 0);
    /** 旋转起始角度,结束角度+Math.PI/2 */
    private readonly startAng: number = -Math.PI / 2;
    /** X坐标最小值  */
    private minX = Number.MAX_SAFE_INTEGER;
    /** X坐标最大值  */
    private maxX = Number.MIN_SAFE_INTEGER;
    /** Y坐标最小值  */
    private minY = Number.MAX_SAFE_INTEGER;
    /** Y坐标最大值  */
    private maxY = Number.MIN_SAFE_INTEGER;

    /**
     * 构造函数
     *
     * @param parent    指向父对象
     * @param data      门数据
     */
    constructor(parent: SGraphItem | null, data: Door) {
        super(parent);
        this.data = data;
        this.zOrder = ItemOrder.doorOrder;
        if (this.data.OutLine.length) {
            this.pointArr = this.data.OutLine[0].map(
                (t): SPoint => {
                    let x = t.X,
                        y = -t.Y;
                    if (x < this.minX) {
                        this.minX = x;
                    }
                    if (y < this.minY) {
                        this.minY = y;
                    }
                    if (x > this.maxX) {
                        this.maxX = x;
                    }
                    if (y > this.maxY) {
                        this.maxY = y;
                    }
                    return new SPoint(t.X, -t.Y);
                }
            );

            let p1 = this.pointArr[0],
                p2 = this.pointArr[1];
            // 旋转点
            this.p = p1;
            const HX = (this.data.HandDirection.X = Number(
                this.data.HandDirection.X.toFixed()
            ));
            const HY = (this.data.HandDirection.Y = Number(
                this.data.HandDirection.Y.toFixed()
            ));
            const FX = (this.data.FaceDirection.X = Number(
                this.data.FaceDirection.X.toFixed()
            ));
            const FY = (this.data.FaceDirection.Y = Number(
                this.data.FaceDirection.Y.toFixed()
            ));
            // 向量点乘 => x1 * x2 + y1 * y2，大于0同向
            let dotProduct = (p2.x - p1.x) * HX + (p2.y - p1.y) * -HY;
            if (dotProduct > 0) {
                this.p = p2;
                p2 = p1;
                p1 = this.p;
            }
            // 两点间距离
            this.r = SMathUtil.pointDistance(p1.x, p1.y, p2.x, p2.y);
            // 门朝向角度
            let fo = Math.atan(-FY / FX);
            this.ang = FX > 0 ? fo : fo + Math.PI;
            // 向量叉乘 => x1 * y2 - x2 * y1,小于0是顺时针
            let direction = (p2.x - p1.x) * -FY - (p2.y - p1.y) * FX;
            if (direction > 0) {
                this.startAng = 0;
            }
        }
    } // Constructor

    /**
     * Item对象边界区域
     *
     * @return SRect
     */
    boundingRect(): SRect {
        return new SRect(
            0,
            0,
            this.r,
            this.r
        );
    } // Function boundingRect()

    /**
     * Item绘制操作
     *
     * @param   painter       painter对象
     */
    onDraw(painter: SPainter): void {
        painter.translate(this.p.x, this.p.y);
        painter.rotate(this.ang);
        painter.pen.lineWidth = painter.toPx(1);
        painter.pen.color = ItemColor.doorColor;
        painter.drawLine(0, 0, this.r, 0);
        painter.pen.lineDash = [50, 100];
        painter.pen.lineWidth = painter.toPx(1);
        // painter.drawArc(
        //     -this.r,
        //     -this.r,
        //     this.r * 2,
        //     this.r * 2,
        //     this.startAng,
        //     this.startAng + Math.PI / 2
        // );
    } // Function onDraw()
} // Class SDoorItem
