import interact from "interactjs";
import { VerdocsEndpoint, updateField } from "@verdocs/js-sdk";
import { h, Host, Fragment } from "@stencil/core";
import { SettingsIcon } from "../../../utils/Icons";
import { Store } from "../../../utils/Datastore";
/**
 * Displays a signature field. If a signature already exists, it will be displayed and the field
 * will be disabled. Otherwise, a placeholder button will be shown. Clicking the button will
 * show a dialog to adopt a signature.
 *
 * NOTE: When signature fields are completed they will be filled with a signature "stamp".
 * This requires operation against a live, valid envelope. If you are testing this component
 * in Storybook, it will not be visible here.
 */
export class VerdocsFieldSignature {
    constructor() {
        /**
         * Fields may be attached to templates or envelopes, but only template fields may be edited.
         */
        this.source = 'template';
        /**
         * The source template or envelope ID the field is found in.
         */
        this.sourceid = '';
        /**
         * The name of the field to display.
         */
        this.fieldname = '';
        /**
         * Override the field's settings. This is intended to be used during signing when fields are being
         * mutated.
         */
        this.field = null;
        /**
         * If set, the signature creation dialog will be initialized with this text.
         */
        this.name = '';
        /**
         * If set, overrides the field's settings object. Primarily used to support "preview" modes where all fields are disabled.
         */
        this.disabled = false;
        /**
         * If set, a settings icon will be displayed on hover. The settings shown allow the field's recipient and other settings to be
         * changed, so it should typically only be enabled in the Builder.
         */
        this.editable = false;
        /**
         * If set, the field may be dragged to a new location. This should only be enabled in the Builder, or for self-placed fields.
         */
        this.moveable = false;
        /**
         * If set, the field is considered "done" and is drawn in a display-final-value state.
         */
        this.done = false;
        /**
         * If set, the field will be be scaled horizontally by this factor.
         */
        this.xscale = 1;
        /**
         * If set, the field will be be scaled vertically by this factor.
         */
        this.yscale = 1;
        /**
         * The page the field is on
         */
        this.pagenumber = 1;
        this.showingProperties = false;
        this.focused = false;
        this.menuOpen = false;
        this.closeMenuTimer = null;
        this.outsideMenuHandler = null;
        this.tempSignature = '';
        this.openMenu = () => {
            if (this.closeMenuTimer) {
                clearTimeout(this.closeMenuTimer);
                this.closeMenuTimer = null;
            }
            this.menuOpen = true;
        };
        this.scheduleCloseMenu = () => {
            if (this.closeMenuTimer) {
                clearTimeout(this.closeMenuTimer);
            }
            this.closeMenuTimer = setTimeout(() => {
                this.menuOpen = false;
                this.closeMenuTimer = null;
            }, 150);
        };
        this.closeMenu = () => {
            if (this.closeMenuTimer) {
                clearTimeout(this.closeMenuTimer);
                this.closeMenuTimer = null;
            }
            this.menuOpen = false;
        };
    }
    handleBlur() {
        this.focused = false;
    }
    async focusField() {
        this.el.focus();
        this.focused = true;
    }
    componentDidLoad() {
        this.outsideMenuHandler = (e) => {
            if (this.menuOpen && !this.el.contains(e.target)) {
                this.closeMenu();
            }
        };
        document.addEventListener('pointerdown', this.outsideMenuHandler);
    }
    disconnectedCallback() {
        if (this.closeMenuTimer) {
            clearTimeout(this.closeMenuTimer);
            this.closeMenuTimer = null;
        }
        if (this.outsideMenuHandler) {
            document.removeEventListener('pointerdown', this.outsideMenuHandler);
            this.outsideMenuHandler = null;
        }
        // Clear any interact.js drag/resize bindings so they don't leak if the DOM element is reused elsewhere
        interact(this.el).unset();
    }
    onEditableChanged(newVal, oldVal) {
        // When transitioning out of editable mode (e.g., builder -> preview tab), clear interact bindings
        if (oldVal && !newVal) {
            interact(this.el).unset();
        }
    }
    componentDidRender() {
        interact.dynamicDrop(true);
        if (this.editable) {
            interact(this.el).resizable({
                edges: {
                    top: '.edge-top',
                    left: '.edge-left',
                    bottom: '.edge-bottom',
                    right: '.edge-right',
                },
                modifiers: [
                    interact.modifiers.restrictSize({
                        min: { width: 71, height: 36 },
                    }),
                ],
                listeners: {
                    start: this.handleResizeStart.bind(this),
                    move: this.handleResize.bind(this),
                    end: this.handleResizeEnd.bind(this),
                },
            });
        }
    }
    onBlur() {
        this.focused = false;
    }
    handleResizeStart(e) {
        e.preventDefault();
        e.stopPropagation();
        e.target.dataset.originalBottom = e.target.style.bottom;
    }
    handleResize(e) {
        let { width, height } = e.rect;
        const dX = e.deltaRect.left;
        const dY = e.deltaRect.bottom;
        const currentLeft = parseFloat(e.target.style.left);
        const currentBottom = parseFloat(e.target.style.bottom);
        width /= this.xscale;
        height /= this.yscale;
        Object.assign(e.target.style, {
            width: `${width}px`,
            height: `${height}px`,
            left: `${currentLeft + dX}px`,
            bottom: `${currentBottom - dY}px`,
        });
    }
    async handleResizeEnd(e) {
        const { sourceid, fieldname } = this;
        const width = Math.round(parseFloat(e.target.style.width));
        let height = Math.round(parseFloat(e.target.style.height));
        if (height < 20) {
            height = 15;
        }
        const newBottom = parseFloat(e.target.style.bottom);
        const originalBottom = parseFloat(e.target.dataset.originalBottom);
        const template = await Store.getTemplate(VerdocsEndpoint.getDefault(), this.sourceid);
        const oldField = template.fields.find(f => f.name === fieldname);
        const y = newBottom !== originalBottom ? newBottom / this.yscale : oldField === null || oldField === void 0 ? void 0 : oldField.y;
        updateField(VerdocsEndpoint.getDefault(), sourceid, fieldname, { width, height, y })
            .then(async (updatedField) => {
            var _a;
            const template = await Store.getTemplate(VerdocsEndpoint.getDefault(), this.sourceid);
            const newTemplate = JSON.parse(JSON.stringify(template));
            const fieldIndex = newTemplate.fields.findIndex(field => field.name === fieldname);
            if (fieldIndex > -1) {
                newTemplate.fields[fieldIndex] = updatedField;
            }
            Store.updateTemplate(this.sourceid, newTemplate);
            (_a = this.settingsChanged) === null || _a === void 0 ? void 0 : _a.emit({ fieldName: fieldname, field: updatedField });
            Object.assign(e.target.dataset, { x: 0, y: 0, h: 0 });
        })
            .catch(e => console.log('Field update failed', e));
    }
    async showSettingsPanel() {
        const settingsPanel = document.getElementById(`verdocs-settings-panel-${this.fieldname}`);
        if (settingsPanel && settingsPanel.showPanel) {
            settingsPanel.showPanel();
        }
    }
    async hideSettingsPanel() {
        const settingsPanel = document.getElementById(`verdocs-settings-panel-${this.fieldname}`);
        if (settingsPanel && settingsPanel.hidePanel) {
            settingsPanel.hidePanel();
        }
        this.showingProperties = false;
    }
    render() {
        const { source, sourceid, fieldname, editable = false, done = false, disabled = false, focused, xscale = 1, yscale = 1 } = this;
        const { index, field } = Store.getField(source, sourceid, fieldname, this.field);
        const { required = false, value = '', label = '', settings = {} } = field || {};
        const { base64 } = settings;
        const signerClass = `signer-${(index % 10) + 1}`;
        if (done) {
            return h(Host, { class: { 'verdocs-field': true, done } }, value && h("img", { src: base64, alt: "" }));
        }
        return (h(Host, { class: { 'verdocs-field': true, required, disabled, done, focused, filled: !!base64, 'menu-open': this.menuOpen, [signerClass]: true } }, editable && h("div", { class: "edge-right" }), editable && h("div", { class: "edge-left" }), editable && h("div", { class: "edge-top" }), editable && h("div", { class: "edge-bottom" }), label && h("label", null, label), base64 ? (h("div", { class: { 'signature-container': true, 'menu-open': this.menuOpen }, onMouseEnter: () => !disabled && this.openMenu(), onMouseLeave: () => this.scheduleCloseMenu(), onClick: e => {
                e.stopPropagation();
                if (disabled)
                    return;
                this.menuOpen ? this.closeMenu() : this.openMenu();
            } }, h("img", { src: base64, alt: "Signature" }), this.menuOpen && (h("div", { class: "action-menu", onMouseEnter: () => this.openMenu(), onMouseLeave: () => this.scheduleCloseMenu() }, h("button", { type: "button", class: "menu-item", onClick: e => {
                e.stopPropagation();
                if (disabled)
                    return;
                console.log('[SIGNATURE] Editing signature');
                this.closeMenu();
                this.adopt.emit();
            } }, "Edit"), h("button", { type: "button", class: "menu-item", onClick: e => {
                var _a;
                e.stopPropagation();
                if (disabled)
                    return;
                console.log('[SIGNATURE] Clearing signature');
                this.closeMenu();
                (_a = this.fieldChange) === null || _a === void 0 ? void 0 : _a.emit(null);
            } }, "Clear"))))) : (h("button", { onClick: () => {
                var _a;
                if (disabled)
                    return;
                // If we already have a signature ID, use it immediately
                if (this.signatureid) {
                    console.log('[SIGNATURE] Reusing existing signature', this.signatureid);
                    (_a = this.fieldChange) === null || _a === void 0 ? void 0 : _a.emit(this.signatureid);
                }
                else {
                    this.adopt.emit();
                }
            } }, "Signature")), editable && (h(Fragment, null, h("div", { id: `verdocs-settings-panel-trigger-${fieldname}`, style: { transform: `scale(${Math.floor((1 / xscale) * 1000) / 1000}, ${Math.floor((1 / yscale) * 1000) / 1000})` }, class: "settings-icon", innerHTML: SettingsIcon, onClick: (e) => {
                e.stopPropagation();
                this.showingProperties = !this.showingProperties;
            } }), this.showingProperties && (h("verdocs-portal", { anchor: `verdocs-settings-panel-trigger-${fieldname}`, onClickAway: () => (this.showingProperties = false) }, h("verdocs-template-field-properties", { templateId: sourceid, fieldName: fieldname, onClose: () => this.hideSettingsPanel(), onDelete: () => {
                var _a;
                (_a = this.deleted) === null || _a === void 0 ? void 0 : _a.emit({ fieldName: fieldname });
                return this.hideSettingsPanel();
            }, onSettingsChanged: e => {
                var _a;
                (_a = this.settingsChanged) === null || _a === void 0 ? void 0 : _a.emit(e.detail);
                return this.hideSettingsPanel();
            }, helpText: "Signature fields capture a recipient's signature on a document." })))))));
    }
    static get is() { return "verdocs-field-signature"; }
    static get originalStyleUrls() {
        return {
            "$": ["verdocs-field-signature.scss"]
        };
    }
    static get styleUrls() {
        return {
            "$": ["verdocs-field-signature.css"]
        };
    }
    static get properties() {
        return {
            "source": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "'template' | 'envelope'",
                    "resolved": "\"envelope\" | \"template\"",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Fields may be attached to templates or envelopes, but only template fields may be edited."
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "attribute": "source",
                "defaultValue": "'template'"
            },
            "sourceid": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "The source template or envelope ID the field is found in."
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "attribute": "sourceid",
                "defaultValue": "''"
            },
            "fieldname": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "The name of the field to display."
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "attribute": "fieldname",
                "defaultValue": "''"
            },
            "field": {
                "type": "unknown",
                "mutable": false,
                "complexType": {
                    "original": "IEnvelopeField | null | undefined",
                    "resolved": "IEnvelopeField",
                    "references": {
                        "IEnvelopeField": {
                            "location": "import",
                            "path": "@verdocs/js-sdk",
                            "id": "node_modules::IEnvelopeField",
                            "referenceLocation": "IEnvelopeField"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Override the field's settings. This is intended to be used during signing when fields are being\nmutated."
                },
                "getter": false,
                "setter": false,
                "defaultValue": "null"
            },
            "name": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "If set, the signature creation dialog will be initialized with this text."
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "attribute": "name",
                "defaultValue": "''"
            },
            "disabled": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "If set, overrides the field's settings object. Primarily used to support \"preview\" modes where all fields are disabled."
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "attribute": "disabled",
                "defaultValue": "false"
            },
            "editable": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "If set, a settings icon will be displayed on hover. The settings shown allow the field's recipient and other settings to be\nchanged, so it should typically only be enabled in the Builder."
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "attribute": "editable",
                "defaultValue": "false"
            },
            "moveable": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "If set, the field may be dragged to a new location. This should only be enabled in the Builder, or for self-placed fields."
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "attribute": "moveable",
                "defaultValue": "false"
            },
            "done": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "If set, the field is considered \"done\" and is drawn in a display-final-value state."
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "attribute": "done",
                "defaultValue": "false"
            },
            "xscale": {
                "type": "number",
                "mutable": false,
                "complexType": {
                    "original": "number",
                    "resolved": "number",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "If set, the field will be be scaled horizontally by this factor."
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "attribute": "xscale",
                "defaultValue": "1"
            },
            "yscale": {
                "type": "number",
                "mutable": false,
                "complexType": {
                    "original": "number",
                    "resolved": "number",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "If set, the field will be be scaled vertically by this factor."
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "attribute": "yscale",
                "defaultValue": "1"
            },
            "pagenumber": {
                "type": "number",
                "mutable": false,
                "complexType": {
                    "original": "number",
                    "resolved": "number",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "The page the field is on"
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "attribute": "pagenumber",
                "defaultValue": "1"
            },
            "signatureid": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "If set, provides the ID of an already-adopted signature. If present, clicking the field (when empty)\nwill immediately use this signature instead of showing the adoption dialog."
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "attribute": "signatureid"
            },
            "isPreview": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "If set to true, it will force interact to unset the el, resulting in no dragging the field."
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "attribute": "is-preview"
            }
        };
    }
    static get states() {
        return {
            "showingProperties": {},
            "focused": {},
            "menuOpen": {},
            "tempSignature": {}
        };
    }
    static get events() {
        return [{
                "method": "fieldChange",
                "name": "fieldChange",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Event emitted when the field has changed."
                },
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                }
            }, {
                "method": "settingsPress",
                "name": "settingsPress",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Event fired on every character entered into / deleted from the field."
                },
                "complexType": {
                    "original": "any",
                    "resolved": "any",
                    "references": {}
                }
            }, {
                "method": "settingsChanged",
                "name": "settingsChanged",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Event fired when the field's settings are changed."
                },
                "complexType": {
                    "original": "{fieldName: string; field: ITemplateField}",
                    "resolved": "{ fieldName: string; field: ITemplateField; }",
                    "references": {
                        "ITemplateField": {
                            "location": "import",
                            "path": "@verdocs/js-sdk",
                            "id": "node_modules::ITemplateField",
                            "referenceLocation": "ITemplateField"
                        }
                    }
                }
            }, {
                "method": "deleted",
                "name": "deleted",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Event fired when the field is deleted."
                },
                "complexType": {
                    "original": "{fieldName: string}",
                    "resolved": "{ fieldName: string; }",
                    "references": {}
                }
            }, {
                "method": "adopt",
                "name": "adopt",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "complexType": {
                    "original": "any",
                    "resolved": "any",
                    "references": {}
                }
            }];
    }
    static get methods() {
        return {
            "focusField": {
                "complexType": {
                    "signature": "() => Promise<void>",
                    "parameters": [],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        }
                    },
                    "return": "Promise<void>"
                },
                "docs": {
                    "text": "",
                    "tags": []
                }
            },
            "showSettingsPanel": {
                "complexType": {
                    "signature": "() => Promise<void>",
                    "parameters": [],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        }
                    },
                    "return": "Promise<void>"
                },
                "docs": {
                    "text": "",
                    "tags": []
                }
            },
            "hideSettingsPanel": {
                "complexType": {
                    "signature": "() => Promise<void>",
                    "parameters": [],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        }
                    },
                    "return": "Promise<void>"
                },
                "docs": {
                    "text": "",
                    "tags": []
                }
            }
        };
    }
    static get elementRef() { return "el"; }
    static get watchers() {
        return [{
                "propName": "editable",
                "methodName": "onEditableChanged"
            }];
    }
    static get listeners() {
        return [{
                "name": "blur",
                "method": "handleBlur",
                "target": undefined,
                "capture": false,
                "passive": false
            }, {
                "name": "blur",
                "method": "onBlur",
                "target": undefined,
                "capture": false,
                "passive": false
            }];
    }
}
//# sourceMappingURL=verdocs-field-signature.js.map
