/* eslint-disable prefer-arrow-callback,react/jsx-one-expression-per-line */
import * as React from 'react';
import { useEffect, useState } from 'react';
import { ActionIcon, Button, Group, Kbd, Popover, Stack, Text } from '@mantine/core';
import { IconChevronDown } from '@tabler/icons-react';
import { useDisclosure, useHotkeys } from '@mantine/hooks';
import { fabric } from 'fabric';
import { MainView } from '@index/components/Tests/Table/Checks/CheckDetails/Canvas/mainView';

interface Props {
    view: string
    mainView: MainView
}

export function ZoomToolbar(
    {
        view,
        mainView,
    }: Props,
) {
    const [zoomPercent, setZoomPercent] = useState(100);
    const [openedZoomPopover, zoomPopoverHandler] = useDisclosure(false);

    /**
     * Calculates the biggest expected or actual image dimension
     * for example: expectedImage {width: 100, height: 200}, actualImage: {width: 200, height: 300}
     * the function will return ['actualImage', 'height' ]
     */
    const calculateMaxImagesDimensions = (): { imageName: string, dimension: string, value: number } => {
        const data: any = [
            { imageName: 'expectedImage', dimension: 'width', value: mainView.expectedImage.width },
            { imageName: 'expectedImage', dimension: 'height', value: mainView.expectedImage.height },
            { imageName: 'actualImage', dimension: 'width', value: mainView.actualImage.width },
            { imageName: 'actualImage', dimension: 'height', value: mainView.actualImage.height },
        ];
        const biggestDimensionValue = Math.max(...data.map((x: any) => x.value));
        return data.find((x: any) => x.value === biggestDimensionValue);
    };

    const zoomByPercent = (percent: number) => {
        if (!mainView?.canvas) return;
        // mainView.canvas.zoomToPoint(new fabric.Point(mainView.canvas.width / 2,
        //     30), percent / 100);
        //
        mainView.canvas.zoomToPoint(
            new fabric.Point(
                // mainView.canvas.viewportTransform[4],
                mainView.canvas.width / 2,
                mainView.canvas.viewportTransform[5],
            ),
            percent / 100,
        );
        document.dispatchEvent(new Event('zoom'));
        // mainView.canvas.renderAll(); console.log('render!!!');
        setZoomPercent(() => percent);
    };

    const zoomByDelta = (delta: number) => {
        document.dispatchEvent(new Event('zoom'));
        let newPercent = Math.round(mainView.canvas.getZoom() * 100) + delta;
        newPercent = newPercent < 2 ? 2 : newPercent;
        newPercent = newPercent > 1000 ? 1000 : newPercent;
        zoomByPercent(newPercent);
    };

    const zoomTo = (image: any, dimension: string) => {
        // @ts-ignore
        const ratio = mainView.canvas[dimension] / image[dimension];
        const percent = ratio > 9 ? 900 : ratio * 100;
        zoomByPercent(percent);
        // mainView.canvas.renderAll(); console.log('render!!!');
    };

    const fitImageToCanvasIfNeeded = (imageName: string) => {
        const image = mainView[imageName as keyof MainView];
        const greatestDimension = (image.height > image.width) ? 'height' : 'width';

        const anotherDimension = (greatestDimension === 'height') ? 'width' : 'height';

        zoomTo(image, greatestDimension);

        if (
            mainView[imageName as keyof MainView][anotherDimension] * mainView.canvas.getZoom()
            > mainView.canvas[anotherDimension]!
        ) {
            zoomTo(mainView[imageName as keyof MainView], anotherDimension);
        }

        mainView.panToCanvasWidthCenter(imageName);
    };

    const fitImageByWith = (imageName: string) => {
        const image = mainView[imageName as keyof MainView];
        zoomTo(image, 'width');

        mainView.panToCanvasWidthCenter(imageName);
    };

    const resizeImageIfNeeded = () => {
        const initPan = (imageName: string) => {
            mainView.panToCanvasWidthCenter(imageName);
        };

        const greatestImage = calculateMaxImagesDimensions();
        // small images
        if (mainView.canvas[greatestImage.dimension] / greatestImage.value > 7) {
            zoomByPercent(350);
            initPan(greatestImage.imageName);
            return;
        }
        // normal images (less than canvas)
        if (greatestImage.value < mainView.canvas[greatestImage.dimension]) {
            initPan(greatestImage.imageName);
            return;
        }

        // large images
        zoomTo(mainView[greatestImage.imageName as keyof MainView], greatestImage.dimension);

        const anotherDimension = (greatestImage.dimension === 'height') ? 'width' : 'height';

        if (
            (mainView[greatestImage.imageName as keyof MainView][anotherDimension] * mainView.canvas.getZoom())
            > mainView.canvas[anotherDimension]!
        ) {
            zoomTo(mainView[greatestImage.imageName as keyof MainView], anotherDimension);
        }

        initPan(greatestImage.imageName);
    };

    useEffect(function oneTime() {
        const zoomEventHandler = () => setZoomPercent(window.mainView.canvas.getZoom() * 100);
        document.addEventListener('zoom', zoomEventHandler, false);
        return () => document.removeEventListener('zoom', zoomEventHandler, false);
    }, []);

    useEffect(
        function initZoom() {
            if (mainView) {
                // zoomEvents();
                resizeImageIfNeeded();
            }
        },
        [mainView?.toString()],
    );

    useHotkeys([
        // Zoom
        ['Equal', () => zoomByDelta(15)],
        ['NumpadAdd', () => zoomByDelta(15)],
        ['Minus', () => zoomByDelta(-15)],
        ['NumpadSubtract', () => zoomByDelta(-15)],
        ['Digit9', () => fitImageByWith(`${view}Image`)],
        ['Digit0', () => {
            if (view === 'slider') {
                fitImageToCanvasIfNeeded('actualImage');
                return;
            }
            fitImageToCanvasIfNeeded(`${view}Image`);
        }],
    ]);

    return (
        <>

            <Popover position="bottom" withArrow shadow="md" opened={openedZoomPopover}>
                <Popover.Target>
                    <Group gap={0} justify="center" onClick={zoomPopoverHandler.toggle} wrap="nowrap" style={{ cursor: 'pointer' }} data-check="open-zoom-dropdown">
                        <Text
                            size="lg"
                            fw={400}
                            style={{ minWidth: '3em' }}
                        >
                            {Math.round(zoomPercent)}%
                        </Text>
                        <ActionIcon ml={-10} style={{ pointerEvents: 'none' }} variant="transparent" color="gray">
                            <IconChevronDown />
                        </ActionIcon>
                    </Group>
                </Popover.Target>
                <Popover.Dropdown p={0}>
                    <Stack gap={0} data-check="zoom-dropdown">
                        <Button
                            pl={8}
                            pr={8}
                            variant="subtle"
                            onClick={() => {
                                zoomByPercent(50);
                                if (view === 'slider') {
                                    mainView.panToCanvasWidthCenter('actualImage');
                                    return;
                                }
                                mainView.panToCanvasWidthCenter(`${view}Image`);
                                zoomPopoverHandler.close();
                            }}
                        >
                            <Group justify="space-between" wrap="nowrap">50%</Group>
                        </Button>
                        <Button
                            pl={8}
                            pr={8}
                            variant="subtle"
                            onClick={() => {
                                zoomByPercent(100);
                                if (view === 'slider') {
                                    mainView.panToCanvasWidthCenter('actualImage');
                                    return;
                                }
                                mainView.panToCanvasWidthCenter(`${view}Image`);
                                zoomPopoverHandler.close();
                            }}
                        >
                            <Group justify="space-between" wrap="nowrap">100%</Group>
                        </Button>
                        <Button
                            pl={8}
                            pr={8}
                            variant="subtle"
                            onClick={() => {
                                zoomByPercent(200);
                                if (view === 'slider') {
                                    mainView.panToCanvasWidthCenter('actualImage');
                                    return;
                                }
                                mainView.panToCanvasWidthCenter(`${view}Image`);
                                zoomPopoverHandler.close();
                            }}
                        >
                            <Group justify="space-between" wrap="nowrap">200%</Group>
                        </Button>
                        <Button
                            styles={{
                                label: {
                                    width: '100%',
                                },
                            }}
                            // style={{ width: '100%' }}
                            pl={8}
                            pr={8}
                            variant="subtle"
                            onClick={() => {
                                zoomPopoverHandler.close();
                                if (view === 'slider') {
                                    fitImageByWith('actualImage');
                                    return;
                                }
                                fitImageByWith(`${view}Image`);
                            }}
                        >
                            <Group style={{ width: '100%' }} justify="space-between" wrap="nowrap">
                                Fit by width <Kbd style={{ fontSize: 11, borderBottomWidth: 1 }}>9</Kbd>
                            </Group>
                        </Button>

                        <Button
                            styles={{
                                label: {
                                    width: '100%',
                                },
                            }}
                            pl={8}
                            pr={8}
                            variant="subtle"
                            onClick={() => {
                                zoomPopoverHandler.close();

                                if (view === 'slider') {
                                    fitImageToCanvasIfNeeded('actualImage');
                                    return;
                                }
                                fitImageToCanvasIfNeeded(`${view}Image`);
                            }}
                        >
                            <Group style={{ width: '100%' }} justify="space-between" wrap="nowrap">
                                Fit to canvas <Kbd style={{ fontSize: 11, borderBottomWidth: 1 }}>0</Kbd>
                            </Group>
                        </Button>
                    </Stack>
                </Popover.Dropdown>
            </Popover>
        </>
    );
}
