import { Vec } from '@tldraw/vec';
import type { TldrawApp } from '@toeverything/components/board-state';
import {
    SessionType,
    TDStatus,
    TldrawCommand,
    TldrawPatch,
} from '@toeverything/components/board-types';
import { BaseSession } from './base-session';
export class LaserSession extends BaseSession {
    type = SessionType.Draw;
    performanceMode: any = undefined;
    status = TDStatus.Creating;
    prevPoint: number[];
    prevEraseShapesSize = 0;

    constructor(app: TldrawApp) {
        super(app);
        this.prevPoint = [...app.originPoint];
        this.interval = this.loop();
    }

    interval: any;
    timestamp1 = 0;
    timestamp2 = 0;
    prevErasePoint: number[] = [];

    loop = () => {
        const now = Date.now();
        const elapsed1 = now - this.timestamp1;
        const elapsed2 = now - this.timestamp2;
        const { laserLine } = this.app.appState;

        let next = [...laserLine];
        let didUpdate = false;

        if (elapsed1 > 16 && this.prevErasePoint !== this.prevPoint) {
            didUpdate = true;
            next = [...laserLine, this.prevPoint];
            this.prevErasePoint = this.prevPoint;
        }

        if (elapsed2 > 32) {
            if (next.length > 1) {
                didUpdate = true;
                next.splice(0, Math.ceil(next.length * 0.1));
                this.timestamp2 = now;
            }
        }

        if (didUpdate) {
            this.app.patchState(
                {
                    appState: {
                        laserLine: next,
                    },
                },
                'eraseline'
            );
        }

        this.interval = requestAnimationFrame(this.loop);
    };

    start = (): TldrawPatch | undefined => void null;

    update = (): TldrawPatch | undefined => {
        const { originPoint, currentPoint } = this.app;

        const newPoint = Vec.toFixed(
            Vec.add(originPoint, Vec.sub(currentPoint, originPoint))
        );

        this.prevPoint = newPoint;

        return {};
    };

    cancel = (): TldrawPatch | undefined => {
        cancelAnimationFrame(this.interval);
        return {
            appState: {
                laserLine: [],
            },
        };
    };

    complete = (): TldrawPatch | TldrawCommand | undefined => {
        const { page } = this.app;

        cancelAnimationFrame(this.interval);

        return {
            before: {
                appState: {
                    laserLine: [],
                },
            },
            after: {
                appState: {
                    laserLine: [],
                },
            },
        };
    };
}
