import { OptionBase, Popup, createElement } from "../ui";

export default class Signature extends OptionBase {
    _var = {
        /**
         * @private
         * @type {HTMLCanvasElement}
         */
        canvas: null,
        /**
         * @private
         * @type {Popup}
         */
        popup: null,
        isDrawing: false,
        /**
         * @private
         * @type {{x: number, y: number}[]}
         */
        points: [],
        /**
         * @private
         * @type {{x: number, y: number}[][]}
         */
        allPoints: []
    };

    /**
     * @event
     * @type {(this: Signature, singature: string) => void}
     */
    onSignatured;

    constructor(opt = {}) {
        super(opt);
    }

    async show() {
        const popup = new Popup({
            title: this.r('FLTL_02770', 'Signature'),
            content: this._var.canvas = createElement('canvas', canvas => {
                canvas.style.width = '100%';
                canvas.style.height = '100%';
            }),
            resolve: result => {
                if (result.result === 'ok' && this._var.allPoints.length > 0) {
                    if (typeof this.onSignatured === 'function') {
                        const data = this._var.canvas.toDataURL('image/png');
                        this.onSignatured(data);
                    }
                } else {
                    if (typeof this.onSignatured === 'function') {
                        this.onSignatured();
                    }
                }
            },
            buttons: [
                {
                    text: this.r('FLTL_02057', 'OK'),
                    trigger: () => {
                        if (this._var.allPoints.length === 0) {
                            return false;
                        }
                        return 'ok';
                    }
                },
                {
                    text: this.r('FLTL_02479', 'Reset'),
                    trigger: () => {
                        const ctx = this._var.canvas.getContext('2d');
                        ctx.clearRect(0, 0, this._var.canvas.width, this._var.canvas.height);
                        return false
                    }
                },
                { text: this.r('FLTL_00499', 'Cancel') }
            ]
        });
        this._var.popup = popup;
        popup.create();
        popup.container.classList.add('ui-popup-signature');
        const mask = await popup.show();
        this.init();
        return mask;
    }

    init() {
        const canvas = this._var.canvas;
        canvas.width = canvas.clientWidth;
        canvas.height = canvas.clientHeight;
        const ctx = canvas.getContext('2d');
        ctx.lineWidth = 3;
        ctx.strokeStyle = '#000';

        canvas.addEventListener('mousedown', e => this._down(ctx, e.offsetX, e.offsetY), false);
        canvas.addEventListener('mousemove', e => this._move(ctx, e.offsetX, e.offsetY), false);
        canvas.addEventListener('mouseup', () => this._up(ctx), false);
    }

    /**
     * @private
     * @param {CanvasRenderingContext2D} ctx 
     * @param {number} x1 
     * @param {number} y1 
     * @param {number} x2 
     * @param {number} y2 
     */
    _draw(ctx, x1, y1, x2, y2) {
        ctx.moveTo(x1, y1);
        ctx.lineTo(x2, y2);
        ctx.stroke();
    }

    /**
     * @private
     * @param {CanvasRenderingContext2D} ctx 
     * @param {number} x 
     * @param {number} y 
     */
    _down(ctx, x, y) {
        this._var.isDrawing = true;
        this._var.points.push({ x, y });
        ctx.beginPath();
    }

    /**
     * @private
     * @param {CanvasRenderingContext2D} ctx 
     * @param {number} x 
     * @param {number} y 
     */
    _move(ctx, x, y) {
        if (this._var.isDrawing) {
            const lastPoint = this._var.points.at(-1);
            this._draw(ctx, lastPoint.x, lastPoint.y, x, y);
            this._var.points.push({ x, y });
        }
    }

    /**
     * @private
     * @param {CanvasRenderingContext2D} ctx 
     */
    _up(ctx) {
        if (this._var.isDrawing) {
            this._var.isDrawing = false;
            ctx.closePath();
            this._var.allPoints.push(this._var.points);
            this._var.points = [];
        }
    }
}