import { IconHelp, IconWindowMaximize, IconWindowMinimize } from '@tabler/icons-react'
import React, { useEffect, useRef, useState } from 'react'
import { clearPrintArea, PrintScale, setPreviousView, setPrintScale, setPrintScaleLine, useMapStore } from '../../../store/map'
import { PrintFormat, PrintOrientation, printResolutions, setPrintOrientation, setPrintResolution, usePrintStore } from '../../../store/print'
import { printDimensions, scaleOptions } from '../../../constants/map'
import { useObjectsStore } from '../../../store/objects'
import jsPDF from 'jspdf'
import { getCenter } from 'ol/extent'
import ScaleLine from 'ol/control/ScaleLine'
import { Button, Checkbox, Dialog, DialogActions, DialogBody, DialogContent, DialogSurface, DialogTitle, Dropdown, Field, Option, Radio, RadioGroup } from '@fluentui/react-components'
import { Dismiss24Regular } from '@fluentui/react-icons'

const MapPrint = ({
    id,
    mapElement
}: {
    id: string
    mapElement: React.MutableRefObject<HTMLDivElement | null>
}) => {
    const [fullscreen, setFullscreen] = useState(false)
    const { printOrientation, printResolution, printFormat } = usePrintStore()
    const { selectedYear, selectedRegion, selectedDistrict } = useObjectsStore().id[id]

    const {
        map,
        mode,
        previousView, printArea, printSource, printAreaDraw, printScale, printScaleLine,
    } = useMapStore().id[id]

    const exportToPDF = (format: PrintFormat, resolution: number, orientation: PrintOrientation) => {
        const dim = printDimensions[format]

        const width = Math.round((dim[orientation === 'horizontal' ? 0 : 1] * resolution) / 25.4)
        const height = Math.round((dim[orientation === 'horizontal' ? 1 : 0] * resolution) / 25.4)

        if (!map) return

        // Store original size and scale
        const originalSize = map.getSize()
        const originalResolution = map.getView().getResolution()

        if (!originalSize || !originalResolution) return

        // Calculate new resolution to fit high DPI
        const scaleFactor = width / originalSize[0]
        const newResolution = originalResolution / scaleFactor

        // Set new high-resolution rendering
        map.setSize([width, height])
        map.getView().setResolution(newResolution)
        map.renderSync()

        map.once("rendercomplete", function () {
            const mapCanvas = document.createElement("canvas")
            mapCanvas.width = width
            mapCanvas.height = height
            const mapContext = mapCanvas.getContext("2d")

            if (!mapContext) return

            const canvas = document.querySelector('canvas')
            if (canvas) {
                if (canvas.width > 0) {
                    const opacity = canvas.parentElement?.style.opacity || "1"
                    mapContext.globalAlpha = parseFloat(opacity)

                    const transform = canvas.style.transform
                    const matrixMatch = transform.match(/^matrix\(([^)]+)\)$/)
                    if (matrixMatch) {
                        const matrix = matrixMatch[1].split(",").map(Number)
                        mapContext.setTransform(...matrix as [number, number, number, number, number, number])
                    }

                    mapContext.drawImage(canvas, 0, 0)
                }
            }

            mapContext.globalAlpha = 1
            mapContext.setTransform(1, 0, 0, 1, 0, 0)

            // Restore original map settings
            map.setSize(originalSize)
            map.getView().setResolution(originalResolution)
            map.renderSync()

            const dimensions = {
                w: orientation === 'horizontal' ? dim[0] : dim[1],
                h: orientation === 'horizontal' ? dim[1] : dim[0]
            }

            // Generate PDF
            const pdf = new jsPDF(orientation === 'horizontal' ? "landscape" : 'portrait', undefined, format)
            pdf.addImage(mapCanvas.toDataURL("image/jpeg"), "JPEG", 0, 0, dimensions.w, dimensions.h)

            const filename = `${selectedYear}-${selectedRegion}-${selectedDistrict}-${new Date().toISOString()}.pdf`
            pdf.save(filename, {
                returnPromise: true
            }).then(() => {

            })
        })
    }

    const scaleLine = useRef(new ScaleLine({
        bar: true,
        text: true,
        minWidth: 125
    }))

    const [opened, setOpened] = useState(false)

    useEffect(() => {
        if (printArea && opened) {
            // backup view before entering print mode
            setPreviousView(id, map?.getView())

            map?.setTarget('print-portal')

            printSource.clear()
            map?.getView().setCenter(getCenter(printArea))
            map?.getView().fit(printArea, {
                size: printOrientation === 'horizontal' ? [594, 420] : [420, 594]
            })
            map?.removeInteraction(printAreaDraw)
        }
    }, [printArea, map, opened])

    useEffect(() => {
        if (printScaleLine && printArea) {
            map?.addControl(scaleLine.current)
        } else {
            map?.removeControl(scaleLine.current)
        }
    }, [printScaleLine, printArea])

    useEffect(() => {
        if (!!printArea) {
            setOpened(true)
        }
    }, [printArea])

    useEffect(() => {
        if (!opened && mode === 'print') {
            clearPrintArea(id)
            map?.setTarget(mapElement.current as HTMLDivElement)
            map?.addInteraction(printAreaDraw)
        }
    }, [opened])

    return (
        <Dialog open={opened}>
            <DialogSurface style={{ maxWidth: fullscreen ? '100%' : 'fit-content', maxHeight: fullscreen ? '100%' : 'fit-content' }}>
                <DialogBody>
                    <DialogTitle action={
                        <div style={{ display: 'flex', marginLeft: 'auto', gap: '1.5rem' }}>
                            <Button appearance='subtle' title='Помощь' style={{ marginLeft: 'auto' }} icon={<IconHelp color='gray' />} />

                            <Button appearance='subtle' title={fullscreen ? 'Свернуть' : 'Развернуть'} style={{ marginLeft: 'auto' }} icon={fullscreen ? <IconWindowMinimize color='gray' /> : <IconWindowMaximize color='gray' />} onClick={() => setFullscreen(!fullscreen)} />

                            <Button appearance='subtle' title='Закрыть' icon={<Dismiss24Regular />} onClick={() => setOpened(false)} />
                        </div>
                    }>Предпросмотр области печати</DialogTitle>

                    <DialogContent style={{ display: 'flex', justifyContent: 'center' }}>
                        <div style={{ display: 'flex', width: 'fit-content', flexDirection: 'row', alignItems: 'flex-start', height: 'fit-content', overflowY: 'auto' }}>                        
                            <div id='print-portal' style={{
                                width: printOrientation === 'horizontal' ? '594px' : '420px',
                                height: printOrientation === 'horizontal' ? '420px' : '594px',
                                flexShrink: '0'
                            }}>

                            </div>

                            <div style={{ display: 'flex', flexDirection: 'column',  width: '100%', flexWrap: 'wrap', gap: '1rem', padding: '1rem', justifyContent: 'space-between', alignItems: 'flex-start' }}>
                                <Field label={'Ориентация'}>
                                    <RadioGroup value={printOrientation} onChange={(_, data) => setPrintOrientation(data.value as PrintOrientation)}>
                                        <Radio value='horizontal' label='Горизонтальная' />
                                        <Radio value='vertical' label='Вертикальная' />
                                    </RadioGroup>
                                </Field>

                                <Field label="Разрешение">
                                    <Dropdown
                                        value={printResolution.toString()}
                                        selectedOptions={[printResolution.toString()]}
                                        onOptionSelect={(_, data) => setPrintResolution(Number(data.optionValue))}
                                    >
                                        {printResolutions.map((res) => (
                                            <Option key={res} text={res} value={res}>
                                                {res}
                                            </Option>
                                        ))}
                                    </Dropdown>
                                </Field>


                                <Field label="Масштаб">
                                    <Dropdown
                                        value={printScale.toString()}
                                        selectedOptions={[printScale]}
                                        onOptionSelect={(_, data) => setPrintScale(id, data.optionValue as PrintScale)}
                                    >
                                        {scaleOptions.map((opt) => (
                                            <Option key={opt.value} text={opt.label} value={opt.value}>
                                                {opt.label}
                                            </Option>
                                        ))}
                                    </Dropdown>
                                </Field>
                            </div>
                        </div>
                    </DialogContent>

                    <DialogActions>
                        <Checkbox
                            checked={printScaleLine}
                            label="Масштабная линия"
                            onChange={(event) => setPrintScaleLine(id, event.currentTarget.checked)}
                        />
                        <Button style={{ marginLeft: 'auto' }} onClick={() => {
                            if (previousView) {
                                exportToPDF(printFormat, printResolution, printOrientation)
                            }
                        }}>
                            Печать
                        </Button>
                    </DialogActions>
                </DialogBody>
            </DialogSurface>
        </Dialog>
    )
}

export default MapPrint