import { Flex, Overlay, Text } from "@mantine/core";
import { ImageToView } from "./ImageViewerProvider";
import { useState } from "react";
import { IconChevronLeft, IconChevronRight, IconImageInPicture, IconX } from "@tabler/icons-react";
import { useRosettaColors } from "@/app/hooks/useRosettaColors";
import { useEffect } from "react";
import { useContextMenu } from "../ContextMenuProvider/useContextMenu";
import { convertJpegBlobToPngBlob, createBlobFromBase64Image } from "@/app/utils/utils";

interface ImageViewerProps {
    images: ImageToView[];
    initialSlide: number;
    onClose: () => void;
}

export function ImageViewer(props : ImageViewerProps) {
    const [slide, setSlide] = useState(props.initialSlide);
    const imageToRender = props.images[slide];
    const colors = useRosettaColors();
    const openContextMenu = useContextMenu();
    const [pos, setPos] = useState({ x: 0, y: 0, scale: 1 });
    const [isDragging, setIsDragging] = useState(false);
    const [wasDragging, setWasDragging] = useState(false);
    const [dragStart, setDragStart] = useState<{x: number, y: number} | null>(null);

    const isNextSlideAvailable = slide + 1 <= props.images.length - 1;
    const isPrevSlideAvailable = slide - 1 >= 0;

    useEffect(() => {
        const handleKeyDown = (e: KeyboardEvent) => {
            if (e.key === "ArrowLeft" && isPrevSlideAvailable) {
                prevSlide(e);
            }
            if (e.key === "ArrowRight" && isNextSlideAvailable) {
                nextSlide(e);
            }
            if (e.key === "Escape") {
                props.onClose();
            }
        };

        window.addEventListener("keydown", handleKeyDown);
        return () => {
            window.removeEventListener("keydown", handleKeyDown);
        };
    }, [slide, isPrevSlideAvailable, isNextSlideAvailable, props.onClose]);

    useEffect(() => {
        setPos({ x: 0, y: 0, scale: 1 });
    }, [slide]);

    const nextSlide = (e : any) => {
        e.stopPropagation();
        if(slide + 1 > props.images.length - 1) {
            return;
        }
        setSlide(slide + 1);
    }

    const prevSlide = (e : any) => {
        e.stopPropagation();
        if(slide - 1 < 0) {
            return;
        }
        setSlide(slide - 1);
    }

    const onContextMenuImg = async () => {
        let blob = await convertJpegBlobToPngBlob(
            createBlobFromBase64Image(imageToRender.src)
        );
        openContextMenu([
            {
                label: 'Copy Image',
                action: async () => {
                    await navigator.clipboard.write([
                        new ClipboardItem({
                            [blob.type]: blob
                        })
                    ]);
                },
                icon: <IconImageInPicture size={14}></IconImageInPicture>
            }
        ]);
    }

    // Wheel zoom (zoom to cursor)
    const onWheel = (e: React.WheelEvent<HTMLImageElement>) => {
        //e.preventDefault();
        const rect = e.currentTarget.getBoundingClientRect();
        const mouseX = e.clientX - rect.left;
        const mouseY = e.clientY - rect.top;
        const prevScale = pos.scale;
        let newScale = prevScale - e.deltaY * 0.004; // ускоренное увеличение
        newScale = Math.max(0.2, Math.min(5, newScale));
        const offsetX = mouseX - pos.x;
        const offsetY = mouseY - pos.y;
        const newX = mouseX - (offsetX * newScale) / prevScale;
        const newY = mouseY - (offsetY * newScale) / prevScale;
        setPos({ ...pos, scale: newScale, x: newX, y: newY });
    };

    // Drag logic
    const onMouseDown = (e: React.MouseEvent<HTMLImageElement | HTMLDivElement>) => {
        if (e.button !== 0) return;
        e.preventDefault();
        e.stopPropagation();
        setIsDragging(true);
        setWasDragging(false);
        setDragStart({ x: e.clientX - pos.x, y: e.clientY - pos.y });
    };
    const onMouseMove = (e: React.MouseEvent<HTMLImageElement | HTMLDivElement>) => {
        if (!isDragging || !dragStart) return;
        setPos({ ...pos, x: e.clientX - dragStart.x, y: e.clientY - dragStart.y });
        setWasDragging(true);
    };
    const onMouseUp = (e: React.MouseEvent<HTMLImageElement | HTMLDivElement>) => {
        e.preventDefault();
        e.stopPropagation();
        setIsDragging(false);
        setDragStart(null);
    };

    return (
        <Overlay
            onClick={() => {
                if (!isDragging && !wasDragging) props.onClose();
            }}
            onMouseDown={onMouseDown}
            onMouseMove={onMouseMove}
            onMouseUp={onMouseUp}
            backgroundOpacity={0.7}
        >
            <Flex direction={'column'} h={'100%'} justify={'space-around'}>
                <Flex justify={'flex-end'} p={'md'}>
                    <IconX size={30} stroke={1} color={'white'} style={{cursor: 'pointer'}} onClick={props.onClose}>
                    </IconX>
                </Flex>
                <Flex justify={'center'} align={'center'} gap={'sm'}>
                    <IconChevronLeft onClick={prevSlide} size={30} color={isPrevSlideAvailable ? 'white' : colors.chevrons.disabled} style={{cursor: 'pointer', userSelect: 'none'}}></IconChevronLeft>
                    <img
                        onContextMenu={() => onContextMenuImg()}
                        src={imageToRender.src}
                        style={{
                            maxWidth: '70vw',
                            maxHeight: '70vh',
                            borderRadius: 8,
                            userSelect: 'none',
                            cursor: isDragging ? 'grabbing' : 'grab',
                            transformOrigin: '0 0',
                            transform: `translate(${pos.x}px, ${pos.y}px) scale(${pos.scale})`,
                        }}
                        onWheel={onWheel}
                        onMouseDown={onMouseDown}
                        onMouseMove={onMouseMove}
                        onMouseUp={onMouseUp}
                        onMouseLeave={onMouseUp}
                        draggable={false}
                    />
                    <IconChevronRight size={30} onClick={nextSlide} color={isNextSlideAvailable ? 'white' : colors.chevrons.disabled} style={{cursor: 'pointer', userSelect: 'none'}}></IconChevronRight>
                </Flex>
                <Flex justify={'center'} gap={'lg'} align={'center'} direction={'row'}>
                    <Text size={'sm'} c={'white'}>
                        {slide + 1} of {props.images.length}
                    </Text>
                    {imageToRender.timestamp &&  
                        <Text size={'sm'} c={'dimmed'}>{new Date(imageToRender.timestamp).toLocaleString()}</Text>
                    }         
                </Flex>
            </Flex>
        </Overlay>
    );
}