const ActionType = {
    Created: 0,
    Saved: 1,
    Sent: 2,
    EmailSent: 3,
    Delivered: 4,
    Seen: 5,
    Signed: 6,
    Rejected: 7,
}

class App {
    constructor(envelopeKey, envelopeReceiver, documentBytes, licenseKey, locale, container) {
        this.container = container ?? `#${this.constructor.name.toLowerCase()}`;
        this.envelopeKey = envelopeKey

        this.Network = new Network()

        this.Instance = null
        this.currentDocument = null
        this.currentReceiver = null
        this.signatureCount = 0;
        this.envelopeReceiver = envelopeReceiver;
        this.documentBytes = documentBytes;
        this.licenseKey = licenseKey;
        this.locale = locale;
    }

    // This function will be called from the ShowEnvelope.razor page
    // and will trigger loading of the Editor Interface
    async init() {
        // Load the envelope from the database
        this.currentDocument = this.envelopeReceiver.envelope.documents[0]
        this.currentReceiver = this.envelopeReceiver.receiver

        // Load the document from the filestore
        const documentResponse = this.documentBytes

        if (documentResponse.fatal || documentResponse.error) {
            return Swal.fire({
                title: 'Fehler',
                text: 'Dokument konnte nicht geladen werden!',
                icon: 'error',
            })
        }

        const arrayBuffer = this.documentBytes

        // Load PSPDFKit
        this.Instance = await UI.loadPSPDFKit(arrayBuffer, this.container, this.licenseKey, this.locale)
        UI.configurePSPDFKit(this.Instance, this.handleClick.bind(this))

        this.Instance.addEventListener(
            'annotations.load',
            this.handleAnnotationsLoad.bind(this)
        )
        this.Instance.addEventListener(
            'annotations.change',
            this.handleAnnotationsChange.bind(this)
        )
        this.Instance.addEventListener(
            'annotations.create',
            this.handleAnnotationsCreate.bind(this)
        )

        this.Instance.addEventListener("annotations.willChange", _ => {
            Comp.ActPanel.Toggle();
          });

        // Load annotations into PSPDFKit
        try {
            this.signatureCount = this.currentDocument.elements.length
            await Annotation.createAnnotations(this.currentDocument, this.Instance)

            const openResponse = await this.Network.openDocument(this.envelopeKey)

            if (openResponse.fatal || openResponse.error) {
                return Swal.fire({
                    title: 'Fehler',
                    text: 'Umschlag konnte nicht geöffnet werden!',
                    icon: 'error',
                })
            }
        } catch (e) {
        }

        //add click events of external buttons
        [...document.getElementsByClassName('btn_refresh')].forEach(btn => btn.addEventListener('click', _ => this.handleClick('RESET')));
        [...document.getElementsByClassName('btn_complete')].forEach(btn => btn.addEventListener('click', _ => this.handleClick('FINISH')));
    }

    handleAnnotationsLoad(loadedAnnotations) {
        loadedAnnotations.toJS()
    }

    handleAnnotationsChange() { }

    async handleAnnotationsCreate(createdAnnotations) {
        const annotation = createdAnnotations.toJS()[0]
        const isFormField = !!annotation.formFieldName
        const isSignature = !!annotation.isSignature

        if (isFormField === false && isSignature === true) {

            const left = annotation.boundingBox.left - 20
            const top = annotation.boundingBox.top - 20
            const width = 150
            const height = 75
            const timestamp = new Date()

            const imageUrl = await Annotation.createAnnotationFrameBlob(
                this.envelopeReceiver.name,
                this.currentReceiver.signature,
                timestamp,
                width,
                height
            )

            const request = await fetch(imageUrl)
            const blob = await request.blob()
            const imageAttachmentId = await this.Instance.createAttachment(blob)

            const frameAnnotation = Annotation.createImageAnnotation(
                new PSPDFKit.Geometry.Rect({
                    left: left,
                    top: top,
                    width: width,
                    height: height,
                }),
                annotation.pageIndex,
                imageAttachmentId
            )

            this.Instance.create(frameAnnotation)
        }
    }

    async handleClick(eventType) {
        let result = false

        switch (eventType) {
            case 'RESET':
                result = await this.handleReset(null)

                if (result.isConfirmed) {
                    Swal.fire({
                        title: 'Erfolg',
                        text: 'Dokument wurde zurückgesetzt',
                        icon: 'info',
                    })
                }

                break

            case 'FINISH':
                result = await this.handleFinish(null)

                if (result == true) {
                    // Redirect to success page after saving to database
                    window.location.href = `/EnvelopeKey/${this.envelopeKey}/Success`
                }

                break

            case 'REJECT':
                alert('Dokument abgelent!')
        }
    }

    async handleFinish(event) {
        const validationResult = await this.validateAnnotations(this.signatureCount)
        if (validationResult === false) {
            Swal.fire({
                title: 'Warnung',
                text: 'Es wurden nicht alle Signaturfelder ausgefüllt!',
                icon: 'warning',
            })
            return false
        }

        return Swal.fire({
            title: localized.confirmation,
            html: `<div class="text-start fs-6 p-0 m-0">${localized.sigAgree}</div>`,
            icon: "question",
            showCancelButton: true,
            confirmButtonColor: "#3085d6",
            cancelButtonColor: "#d33",
            confirmButtonText: localized.finalize,
            cancelButtonText: localized.back
        }).then(async (result) => {
            if (result.isConfirmed) {
                //---
                // Save changes before doing anything
                try {
                    await this.Instance.save()
                } catch (e) {
                    Swal.fire({
                        title: 'Fehler',
                        text: 'Umschlag konnte nicht signiert werden!',
                        icon: 'error',
                    })
                    return false
                }

                // Export annotation data and save to database
                try {
                    const json = await this.Instance.exportInstantJSON()
                    const postEnvelopeResult = await this.Network.postEnvelope(
                        this.envelopeKey,
                        this.currentDocument.id,
                        json
                    )

                    if (postEnvelopeResult.fatal) {
                        Swal.fire({
                            title: 'Fehler',
                            text: 'Umschlag konnte nicht signiert werden!',
                            icon: 'error',
                        })
                        return false
                    }

                    if (postEnvelopeResult.error) {
                        Swal.fire({
                            title: 'Warnung',
                            text: 'Umschlag ist nicht mehr verfügbar.',
                            icon: 'warning',
                        })
                        return false
                    }

                    return true
                } catch (e) {
                    return false
                }
                //---
            }
            else
                return false;
        });
    }


    async validateAnnotations(totalSignatures) {
        const annotations = await Annotation.getAnnotations(this.Instance)
        const filtered = annotations
            .map(a => a.toJS())
            .filter(a => a.isSignature)

        if (totalSignatures > filtered.length) {
            return false
        } else {
            return true
        }
    }

    async handleReset(event) {
        const result = await Swal.fire({
            title: 'Sind sie sicher?',
            text: 'Wollen Sie das Dokument und alle erstellten Signaturen zurücksetzen?',
            icon: 'question',
            showCancelButton: true
        })

        if (result.isConfirmed) {
            const result = await Annotation.deleteAnnotations(this.Instance)
        }

        return result
    }
}
