import Point from './Point';

const shadowLength = 2000; // TODO: should be calculated

export default class Box {
    public position: Point;
    private angle: number;
    public color: string;
    private readonly shadowColor: string;

    private _size: number;
    private _halfSize: number;

    constructor(size: number, position: Point, startRotate: number, color: string, shadowColor: string) {
        this.size = size;
        this.position = position;
        this.color = color;
        this.angle = startRotate;
        this.shadowColor = shadowColor;
    }

    public get size(): number {
        return this._size;
    }

    public set size(size: number) {
        this._size = size;
        this._halfSize = Math.floor(size / 2);
    }

    public get halfSize(): number {
        return this._halfSize;
    }

    get points(): { p1: Point; p2: Point; p3: Point; p4: Point } {
        const full = (Math.PI * 2) / 4;

        const p1: Point = {
            x: this.position.x + this._halfSize * Math.sin(this.angle),
            y: this.position.y + this._halfSize * Math.cos(this.angle),
        };

        const p2: Point = {
            x: this.position.x + this._halfSize * Math.sin(this.angle + full),
            y: this.position.y + this._halfSize * Math.cos(this.angle + full),
        };

        const p3: Point = {
            x: this.position.x + this._halfSize * Math.sin(this.angle + full * 2),
            y: this.position.y + this._halfSize * Math.cos(this.angle + full * 2),
        };

        const p4: Point = {
            x: this.position.x + this._halfSize * Math.sin(this.angle + full * 3),
            y: this.position.y + this._halfSize * Math.cos(this.angle + full * 3),
        };

        return { p1, p2, p3, p4 };
    }

    rotate(): void {
        const speed = (60 - this._halfSize) / 20;
        this.angle += speed * 0.002;
        this.position.x += speed;
        this.position.y += speed;
    }

    draw(ctx: CanvasRenderingContext2D): void {
        const { points } = this;
        ctx.beginPath();
        ctx.moveTo(points.p1.x, points.p1.y);
        ctx.lineTo(points.p2.x, points.p2.y);
        ctx.lineTo(points.p3.x, points.p3.y);
        ctx.lineTo(points.p4.x, points.p4.y);
        ctx.fillStyle = this.color;
        ctx.fill();
    }

    drawShadow(ctx: CanvasRenderingContext2D, light: Point): void {
        const boxPoints = this.points;
        const points: Array<{
            startX: number;
            startY: number;
            endX: number;
            endY: number;
        }> = [];

        Object.values(boxPoints).forEach((point) => {
            const angle = Math.atan2(light.y - point.y, light.x - point.x);
            const endX = point.x + shadowLength * Math.sin(-angle - Math.PI / 2);
            const endY = point.y + shadowLength * Math.cos(-angle - Math.PI / 2);
            points.push({
                startX: point.x,
                startY: point.y,
                endX,
                endY,
            });
        });

        for (let i = points.length - 1; i >= 0; i--) {
            const n = i === 3 ? 0 : i + 1;
            ctx.beginPath();
            ctx.moveTo(points[i].startX, points[i].startY);
            ctx.lineTo(points[n].startX, points[n].startY);
            ctx.lineTo(points[n].endX, points[n].endY);
            ctx.lineTo(points[i].endX, points[i].endY);
            ctx.fillStyle = this.shadowColor;
            ctx.fill();
        }
    }
}
