class Annotation {
    static async createAnnotations(document, instance) {
        const signatures = []

        for (var element of document.elements) {
            const [annotation, formField, annotation_date, formFieldDate, annotation_city, formFieldCity, annotation_date_label, formFieldDateLabel, annotation_city_label, formFieldCityLabel] = await Annotation.createSignature(element)
            signatures.push(annotation)
            signatures.push(formField)
            signatures.push(annotation_date)
            signatures.push(formFieldDate)
            signatures.push(annotation_city)
            signatures.push(formFieldCity)

            signatures.push(annotation_date_label)
            signatures.push(formFieldDateLabel)

            signatures.push(annotation_city_label)
            signatures.push(formFieldCityLabel)
        }

        await instance.create(signatures)
    }

    static async createSignature(element) {
        const id = PSPDFKit.generateInstantId()
        const width = Annotation.inchToPoint(element.width)
        const height = Annotation.inchToPoint(element.height)
        const top = Annotation.inchToPoint(element.top) - height / 2
        const left = Annotation.inchToPoint(element.left) - width / 2
        const page = element.page - 1

        //signatures
        const annotation = new PSPDFKit.Annotations.WidgetAnnotation({
            id: id,
            pageIndex: page,
            formFieldName: id,
            backgroundColor: PSPDFKit.Color.YELLOW,
            blendMode: 'multiply',
            boundingBox: new PSPDFKit.Geometry.Rect({
                width,
                height,
                top,
                left,
            }),
        })

        const formField = new PSPDFKit.FormFields.SignatureFormField({
            name: id,
            annotationIds: PSPDFKit.Immutable.List([annotation.id]),
        })

        /**
         * Date, post code and place text form part
         */
        const date_place_top_shift = 16
        //date
        const id_date = PSPDFKit.generateInstantId()
        const annotation_date = new PSPDFKit.Annotations.WidgetAnnotation({
            id: id_date,
            pageIndex: page,
            formFieldName: id_date,
            backgroundColor: PSPDFKit.Color.DarkBlue,
            blendMode: 'multiply',
            boundingBox: new PSPDFKit.Geometry.Rect({
                width: width * 0.75,
                height: height / 2,
                top: top + height + 25 + date_place_top_shift,
                left: left - width * .25 + width * 1.30,
            }),
            fontSize: 8,
            backgroundColor: PSPDFKit.Color.TRANSPARENT,
            fontColor: PSPDFKit.Color.Black,
            isBold: true,
            required: true
        })

        const formFieldDate = new PSPDFKit.FormFields.TextFormField({
            name: id_date,
            annotationIds: PSPDFKit.Immutable.List([annotation_date.id]),
            value: locale_date_dd_mm_yyyy(),
            readOnly: true
        })
        
        //city
        var location = await getLocation();
        const id_city = PSPDFKit.generateInstantId()
        const annotation_city = new PSPDFKit.Annotations.WidgetAnnotation({
            id: id_city,
            pageIndex: page,
            formFieldName: id_city,
            backgroundColor: PSPDFKit.Color.DarkBlue,
            blendMode: 'multiply',
            boundingBox: new PSPDFKit.Geometry.Rect({
                width: width * 1.2,
                height: height / 2,
                top: top + height + 25 + date_place_top_shift,
                left: left - width * .25,
            }),
            fontSize: 8
        })
        
        const formFieldCity = new PSPDFKit.FormFields.TextFormField({
            name: id_city,
            annotationIds: PSPDFKit.Immutable.List([annotation_city.id]),
            value: location.city,
            readOnly: isMobile()
        })

        /**
         * Date, post code and place label part
         */
        const label_top_shift = -15

        //date label
        const id_date_label = PSPDFKit.generateInstantId()
        const annotation_date_label = new PSPDFKit.Annotations.WidgetAnnotation({
            id: id_date_label,
            pageIndex: page,
            formFieldName: id_date_label,
            blendMode: 'multiply',
            boundingBox: new PSPDFKit.Geometry.Rect({
                width: width * 0.75,
                height: height / 2,
                top: top + height + 25 + label_top_shift + date_place_top_shift,
                left: left - width * .25 + width * 1.30
            }),
            fontSize: 8,
            backgroundColor: PSPDFKit.Color.TRANSPARENT,
            fontColor: PSPDFKit.Color.Black,
            isBold: true,
            required: true
        })

        const formFieldDateLabel = new PSPDFKit.FormFields.TextFormField({
            name: id_date_label,
            annotationIds: PSPDFKit.Immutable.List([annotation_date_label.id]),
            value: "Date",
            readOnly: true
        })

        //city label
        const id_city_label = PSPDFKit.generateInstantId()
        const annotation_city_label = new PSPDFKit.Annotations.WidgetAnnotation({
            id: id_city_label,
            pageIndex: page,
            formFieldName: id_city_label,
            blendMode: 'multiply',
            boundingBox: new PSPDFKit.Geometry.Rect({
                width: width * 1.2,
                height: height / 2,
                top: top + height + 25 + label_top_shift + date_place_top_shift,
                left: left - width * .25
            }),
            fontSize: 8,
            backgroundColor: PSPDFKit.Color.TRANSPARENT,
            fontColor: PSPDFKit.Color.Black,
            isBold: true,
        })

        const formFieldCityLabel = new PSPDFKit.FormFields.TextFormField({
            name: id_city_label,
            annotationIds: PSPDFKit.Immutable.List([annotation_city_label.id]),
            value: "Ort",
            readOnly: true
        })

        return [annotation, formField, annotation_date, formFieldDate, annotation_city, formFieldCity, annotation_date_label, formFieldDateLabel, annotation_city_label, formFieldCityLabel]
    }

    static createTextBox(element) {
        const id = PSPDFKit.generateInstantId()
        const width = Annotation.inchToPoint(element.width)
        const height = Annotation.inchToPoint(element.height)
        const top = Annotation.inchToPoint(element.top) - height / 2
        const left = Annotation.inchToPoint(element.left) - width / 2
        const page = element.page - 1

        //shift
        top += height + 10

        const annotation = new PSPDFKit.Annotations.WidgetAnnotation({
            id: id,
            pageIndex: page,
            formFieldName: id,
            backgroundColor: PSPDFKit.Color.YELLOW,
            blendMode: 'multiply',
            boundingBox: new PSPDFKit.Geometry.Rect({
                width,
                height,
                top,
                left,
            }),
        })

        const formField = new PSPDFKit.FormFields.SignatureFormField({
            name: id,
            annotationIds: PSPDFKit.Immutable.List([annotation.id]),
        })

        return [annotation, formField]
    }

    static async getAnnotations(instance) {
        const array = await Promise.all(
            Array.from({ length: instance.totalPageCount }).map((_, pageIndex) =>
                instance.getAnnotations(pageIndex)
            )
        )

        return array.flatMap((annotations) =>
            annotations.reduce((acc, annotation) => acc.concat(annotation), [])
        )
    }

    static async deleteAnnotations(instance) {
        const allAnnotations = await Annotation.getAnnotations(instance)
        const pageAnnotations = allAnnotations.filter(Annotation.isSignature)
        //deleting all Annotations
        return await instance.delete(pageAnnotations)
    }

    static async validateAnnotations(instance) {
        const allAnnotations = await Annotation.getAnnotations(instance)
        const pageAnnotations = allAnnotations
            .map((annotation) => {
                return annotation
            })

        return true
    }

    static isSignature(annotation) {
        return !!annotation.isSignature || annotation.description == 'FRAME'
    }

    static createImageAnnotation(boundingBox, pageIndex, imageAttachmentId) {
        const frameAnnotation = new PSPDFKit.Annotations.ImageAnnotation({
            pageIndex: pageIndex,
            isSignature: false,
            readOnly: true,
            locked: true,
            lockedContents: true,
            contentType: 'image/png',
            imageAttachmentId,
            description: 'FRAME',
            boundingBox: boundingBox,
        })
        return frameAnnotation
    }

    static async createAnnotationFrameBlob(receiverName, receiverSignature, timestamp, width, height) {
        const canvas = document.createElement('canvas')
        const scale = 4
        const fontSize = 10

        canvas.width = width * scale
        canvas.height = height * scale

        const ctx = canvas.getContext('2d')
        // This supposedly makes the lines and text less blurry
        // See: https://stackoverflow.com/questions/8696631/canvas-drawings-like-lines-are-blurry
        ctx.translate(0.5, 0.5)

        // This also should make the lines and text less blurry
        ctx.textRendering = "geometricPrecision"

        const date = timestamp
        const dateString = date.toLocaleString('de-DE')

        const signatureLength = 100 * scale
        const signatureString = receiverSignature.substring(0, 15) + "…"

        ctx.beginPath()

        ctx.moveTo(30 * scale, 10 * scale)
        ctx.lineTo(signatureLength, 10 * scale)

        ctx.moveTo(30 * scale, 10 * scale)
        ctx.arcTo(10 * scale, 10 * scale, 10 * scale, 30 * scale, 20 * scale)

        ctx.moveTo(10 * scale, 30 * scale)
        ctx.arcTo(10 * scale, 50 * scale, 30 * scale, 50 * scale, 20 * scale)

        ctx.moveTo(30 * scale, 50 * scale)
        ctx.lineTo(signatureLength, 50 * scale)

        ctx.strokeStyle = 'darkblue'
        ctx.stroke()

        ctx.fillStyle = 'black'
        ctx.font = `${fontSize * scale}px sans-serif`
        ctx.fillText('Signed by', 15 * scale, 10 * scale)
        ctx.fillText(receiverName, 15 * scale, 60 * scale)
        ctx.fillText(signatureString, 15 * scale, 70 * scale)

        return new Promise((resolve) => {
            canvas.toBlob((blob) => {
                const url = URL.createObjectURL(blob)
                resolve(url)
            })
        })
    }

    static inchToPoint(inch) {
        return inch * 72
    }
}
