import { cancelEnvelope, getDocumentDownloadLink, getEnvelope, integerSequence, userCanCancelEnvelope, VerdocsEndpoint } from "@verdocs/js-sdk";
import { h, Host, Fragment } from "@stencil/core";
import { saveEnvelopesAsZip } from "../../../utils/utils";
import { SDKError } from "../../../utils/errors";
import { Store } from "../../../utils/Datastore";
/**
 * Render the documents attached to an envelope in read-only (view) mode. All documents are
 * displayed in order.
 *
 * ```ts
 * <verdocs-view
 *   envelopeId={ENVELOPE_ID}
 *   onSdkError={({ detail }) => { console.log('SDK error', detail) }
 *   />
 * ```
 */
export class VerdocsView {
    constructor() {
        this.envelopeListenerId = null;
        /**
         * The endpoint to use to communicate with Verdocs. If not set, the default endpoint will be used.
         */
        this.endpoint = null;
        /**
         * The envelope ID to render. Set ONE OF templateId or envelopeId. If both are set, envelopeId will be ignored.
         */
        this.envelopeId = '';
        /**
         * If set, (recommended), the host application should create a <DIV> element with a unique ID. When this
         * component renders, the header will be removed from its default location and placed in the target element.
         * This allows the parent application to more easily control its placement and scroll effects (e.g. "fixed").
         *
         * The movement of the header to the target container is not dynamic - it is performed only on the initial
         * render. Host applications should not conditionally render this container. If the header's visibility must
         * be externally controlled, use CSS display options to hide/show it instead.
         */
        this.headerTargetId = null;
        this.canceling = false;
        this.showCancelDone = false;
        this.showLoadError = false;
        this.loading = true;
        this.envelope = null;
    }
    async componentWillLoad() {
        var _a, _b, _c;
        if (!this.endpoint) {
            this.endpoint = VerdocsEndpoint.getDefault();
            this.endpoint.loadSession();
        }
        if (!this.envelopeId) {
            console.error(`[VIEW] Missing required envelopeId`);
            return;
        }
        this.listenToEnvelope();
        if (!this.envelope) {
            try {
                console.log('[VIEW] Loading envelope...');
                this.envelope = await getEnvelope(this.endpoint, this.envelopeId);
                console.log('[VIEW] Loaded envelope', this.envelope);
            }
            catch (e) {
                this.showLoadError = true;
                (_a = this.sdkError) === null || _a === void 0 ? void 0 : _a.emit(new SDKError(e.message, (_b = e.response) === null || _b === void 0 ? void 0 : _b.status, (_c = e.response) === null || _c === void 0 ? void 0 : _c.data));
            }
        }
    }
    componentDidRender() {
        const headerTarget = this.headerTargetId ? document.getElementById(this.headerTargetId) : null;
        const headerEl = document.getElementById('verdocs-view-header');
        if (headerTarget && headerEl) {
            console.log('[VIEW] Moving header');
            headerEl.remove();
            headerTarget.append(headerEl);
        }
    }
    disconnectedCallback() {
        this.unlistenToEnvelope();
    }
    async listenToEnvelope() {
        console.log('[SIDEBAR] Loading envelope', this.envelopeId);
        this.unlistenToEnvelope();
        Store.subscribe('envelopes', this.envelopeId, () => getEnvelope(this.endpoint, this.envelopeId), true, (envelope) => {
            this.envelope = envelope;
            this.loading = false;
        });
    }
    unlistenToEnvelope() {
        if (this.envelopeListenerId) {
            Store.store.delListener(this.envelopeListenerId);
            this.envelopeListenerId = null;
        }
    }
    handlePageRendered(_e) {
        // const pageInfo = e.detail as IDocumentPageInfo;
        // console.log('[VIEW] Page rendered', pageInfo);
    }
    async handleOptionSelected(e) {
        var _a, _b;
        switch (e.detail.id) {
            case 'cancel':
                // TODO: Better option for inline-flow confirmation and alert dialogs.
                if (confirm('Are you sure you wish to cancel this envelope? This action cannot be undone.')) {
                    this.canceling = true;
                    cancelEnvelope(this.endpoint, this.envelopeId)
                        .then(r => {
                        this.canceling = false;
                        console.log('[VIEW] Envelope canceled', r);
                        return getEnvelope(this.endpoint, this.envelopeId);
                    })
                        .then(env => {
                        console.log('[VIEW] Loaded new envelope details', env);
                        this.envelope = env;
                    })
                        .catch(e => {
                        var _a, _b, _c;
                        this.canceling = false;
                        console.log('[VIEW] Error canceling envelope', e);
                        (_a = this.sdkError) === null || _a === void 0 ? void 0 : _a.emit(new SDKError(e.message, (_b = e.response) === null || _b === void 0 ? void 0 : _b.status, (_c = e.response) === null || _c === void 0 ? void 0 : _c.data));
                    });
                    this.showCancelDone = true;
                    (_a = this.envelopeUpdated) === null || _a === void 0 ? void 0 : _a.emit({ endpoint: this.endpoint, envelope: this.envelope, event: 'canceled' });
                }
                break;
            case 'print':
                window.print();
                (_b = this.envelopeUpdated) === null || _b === void 0 ? void 0 : _b.emit({ endpoint: this.endpoint, envelope: this.envelope, event: 'printed' });
                break;
            case 'download-attachments':
                // TODO: Multiple document support
                {
                    const firstDoc = this.envelope.documents.find(doc => doc.type === 'attachment');
                    if (firstDoc) {
                        const url = await getDocumentDownloadLink(this.endpoint, this.envelopeId, firstDoc.id);
                        window.open(url, '_blank');
                    }
                }
                break;
            case 'download-certificate':
                // TODO: Multiple certificate support
                {
                    const firstCert = this.envelope.documents.find(doc => doc.type === 'certificate');
                    if (firstCert) {
                        const url = await getDocumentDownloadLink(this.endpoint, this.envelopeId, firstCert.id);
                        window.open(url, '_blank');
                    }
                }
                // saveCertificate(this.endpoint, this.envelope, this.envelope.certificate_document_id)
                //   .then(() => {
                //     this.envelopeUpdated?.emit({endpoint: this.endpoint, envelope: this.envelope, event: 'downloaded'});
                //   })
                //   .catch(e => {
                //     console.log('Error downloading PDF', e);
                //   });
                break;
            case 'download-all':
                saveEnvelopesAsZip(this.endpoint, [this.envelope])
                    .then(() => {
                    var _a;
                    (_a = this.envelopeUpdated) === null || _a === void 0 ? void 0 : _a.emit({ endpoint: this.endpoint, envelope: this.envelope, event: 'downloaded' });
                })
                    .catch(e => {
                    console.log('Error downloading Zip', e);
                });
                break;
        }
    }
    render() {
        var _a;
        if (this.loading) {
            return (h(Host, null, h("verdocs-loader", null)));
        }
        if (this.showLoadError) {
            return (h(Host, null, h("verdocs-ok-dialog", { heading: "Unable to View Envelope", message: `Sorry, that envelope is not valid.`, buttonLabel: "OK", onNext: () => {
                    this.showLoadError = false;
                } })));
        }
        if (!this.envelope) {
            return (h(Host, null, h("img", { src: "https://public-assets.verdocs.com/loading-placeholder.png", style: { width: '612px', height: '792px', boxShadow: '0 0 10px 5px #0000000f', marginTop: '15px' }, alt: "Placeholder page" })));
        }
        const menuOptions = [{ id: 'print', label: 'Print' }];
        if (userCanCancelEnvelope(this.endpoint.profile, this.envelope)) {
            menuOptions.push({ id: 'cancel', label: 'Cancel' });
        }
        // Add download options to the menu
        const hasAttachments = this.envelope.documents.length > 0;
        const normalDocCount = this.envelope.documents.filter(doc => doc.type === 'attachment').length;
        const hasCertificate = this.envelope.documents.find(doc => doc.type === 'certificate') !== undefined;
        if (hasAttachments || hasCertificate) {
            menuOptions.push({ label: '' });
            if (hasAttachments) {
                menuOptions.push({ id: 'download-attachments', label: normalDocCount > 1 ? 'Download Documents' : 'Download Document' });
            }
            if (hasCertificate) {
                menuOptions.push({ id: 'download-certificate', label: 'Download Certificate' });
            }
            if (hasAttachments && hasCertificate) {
                menuOptions.push({ id: 'download-all', label: 'Download All Files' });
            }
        }
        return (h(Host, null, h("div", { id: "verdocs-view-header" }, h("div", { class: "inner" }, h("img", { src: "https://verdocs.com/assets/white-logo.svg", alt: "Verdocs Logo", class: "logo" }), h("div", { class: "title" }, this.envelope.name), h("div", { style: { flex: '1' } }), h("div", { style: { marginLeft: '10px' } }), h("verdocs-dropdown", { options: menuOptions, onOptionSelected: e => this.handleOptionSelected(e) }))), h("div", { class: "document", style: { paddingTop: this.headerTargetId ? '70px' : '15px' } }, (((_a = this.envelope) === null || _a === void 0 ? void 0 : _a.documents) || [])
            .filter(document => document.type !== 'certificate')
            .map(envelopeDocument => {
            const pageNumbers = integerSequence(1, envelopeDocument.pages);
            return (h(Fragment, null, pageNumbers.map(pageNumber => {
                var _a;
                const pageSize = ((_a = envelopeDocument.page_sizes) === null || _a === void 0 ? void 0 : _a[pageNumber]) || { width: 612, height: 792 };
                return (h("verdocs-envelope-document-page", { envelopeId: this.envelopeId, documentId: envelopeDocument.id, endpoint: this.endpoint, type: "filled", virtualWidth: pageSize.width, virtualHeight: pageSize.height, pageNumber: pageNumber, onPageRendered: e => this.handlePageRendered(e), layers: [
                        { name: 'page', type: 'canvas' },
                        { name: 'controls', type: 'div' },
                    ] }));
            })));
        })), this.showCancelDone && (h("verdocs-ok-dialog", { heading: "Cancelled", message: `This envelope has been cancelled successfully.`, onNext: () => {
                this.showCancelDone = false;
            } })), this.canceling && (h("div", { class: "loading-indicator" }, h("verdocs-loader", null)))));
    }
    static get is() { return "verdocs-view"; }
    static get originalStyleUrls() {
        return {
            "$": ["verdocs-view.scss"]
        };
    }
    static get styleUrls() {
        return {
            "$": ["verdocs-view.css"]
        };
    }
    static get properties() {
        return {
            "endpoint": {
                "type": "unknown",
                "attribute": "endpoint",
                "mutable": false,
                "complexType": {
                    "original": "VerdocsEndpoint | null",
                    "resolved": "VerdocsEndpoint",
                    "references": {
                        "VerdocsEndpoint": {
                            "location": "import",
                            "path": "@verdocs/js-sdk",
                            "id": "node_modules::VerdocsEndpoint"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "The endpoint to use to communicate with Verdocs. If not set, the default endpoint will be used."
                },
                "getter": false,
                "setter": false,
                "defaultValue": "null"
            },
            "envelopeId": {
                "type": "string",
                "attribute": "envelope-id",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "The envelope ID to render. Set ONE OF templateId or envelopeId. If both are set, envelopeId will be ignored."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "''"
            },
            "headerTargetId": {
                "type": "string",
                "attribute": "header-target-id",
                "mutable": false,
                "complexType": {
                    "original": "string | null",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "If set, (recommended), the host application should create a <DIV> element with a unique ID. When this\ncomponent renders, the header will be removed from its default location and placed in the target element.\nThis allows the parent application to more easily control its placement and scroll effects (e.g. \"fixed\").\n\nThe movement of the header to the target container is not dynamic - it is performed only on the initial\nrender. Host applications should not conditionally render this container. If the header's visibility must\nbe externally controlled, use CSS display options to hide/show it instead."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "null"
            }
        };
    }
    static get states() {
        return {
            "canceling": {},
            "showCancelDone": {},
            "showLoadError": {},
            "loading": {},
            "envelope": {}
        };
    }
    static get events() {
        return [{
                "method": "sdkError",
                "name": "sdkError",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Event fired if an error occurs. The event details will contain information about the error. Most errors will\nterminate the process, and the calling application should correct the condition and re-render the component."
                },
                "complexType": {
                    "original": "SDKError",
                    "resolved": "SDKError",
                    "references": {
                        "SDKError": {
                            "location": "import",
                            "path": "../../../utils/errors",
                            "id": "src/utils/errors.ts::SDKError"
                        }
                    }
                }
            }, {
                "method": "envelopeUpdated",
                "name": "envelopeUpdated",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Event fired when the envelope is updated in any way. May be used for tasks such as cache invalidation or reporting to other systems."
                },
                "complexType": {
                    "original": "{endpoint: VerdocsEndpoint; envelope: IEnvelope; event: string}",
                    "resolved": "{ endpoint: VerdocsEndpoint; envelope: IEnvelope; event: string; }",
                    "references": {
                        "VerdocsEndpoint": {
                            "location": "import",
                            "path": "@verdocs/js-sdk",
                            "id": "node_modules::VerdocsEndpoint"
                        },
                        "IEnvelope": {
                            "location": "import",
                            "path": "@verdocs/js-sdk",
                            "id": "node_modules::IEnvelope"
                        }
                    }
                }
            }, {
                "method": "another",
                "name": "another",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Event fired when the user clicks Send Another to proceed. It is up to the host application\nto redirect the user to the appropriate next workflow step."
                },
                "complexType": {
                    "original": "any",
                    "resolved": "any",
                    "references": {}
                }
            }, {
                "method": "view",
                "name": "view",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Event fired when the user clicks Send Another to proceed. It is up to the host application\nto redirect the user to the appropriate next workflow step."
                },
                "complexType": {
                    "original": "any",
                    "resolved": "any",
                    "references": {}
                }
            }, {
                "method": "next",
                "name": "next",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Event fired when the user clicks Done to proceed. It is up to the host application\nto redirect the user to the appropriate next workflow step."
                },
                "complexType": {
                    "original": "any",
                    "resolved": "any",
                    "references": {}
                }
            }];
    }
    static get elementRef() { return "component"; }
}
//# sourceMappingURL=verdocs-view.js.map
