import React, {useEffect, useRef, useState} from "react";
import {
    getDocument,
    GlobalWorkerOptions,
    PageViewport,
    PDFDocumentProxy,
    PDFPageProxy,
    renderTextLayer
} from "pdfjs-dist";
import "./PDFViewer.css"
import {Button, Dropdown, Input, MenuProps, Modal, Progress, Space, Tooltip} from "antd";
import {
    CaretLeftOutlined,
    CaretRightOutlined, DownloadOutlined, FullscreenOutlined,
    PercentageOutlined, PrinterOutlined,
    ZoomInOutlined,
    ZoomOutOutlined
} from "@ant-design/icons";
import html2canvas from "html2canvas";
import {PDFDocument, PDFPage} from "pdf-lib";
import {PasswordException} from "pdfjs-dist/types/src/shared/util";
import { jsPDF } from "jspdf";

const PdfjsVersion:string = "3.11.174";
GlobalWorkerOptions.workerSrc = `https://unpkg.com/pdfjs-dist@${PdfjsVersion}/build/pdf.worker.min.js`;

interface PdfViewerProps {
    fileUrl: string;
    fileName?:string;
    downloadFileUrl?:string;
    scale?:number;
    renderText?:boolean;
    waterMarkText?:string;
}

async function loadPage(pdf:PDFDocumentProxy, pageNum:number, scale:number, rotate:number, container:HTMLDivElement, isRenderText:boolean, waterMarkText:string|undefined)
{
    const pageLayer = document.createElement("div");
    const canvas = document.createElement("canvas");
    const cavasLayer = document.createElement("div");
    const loadingLayer = document.createElement("div");
    const drawLayer = document.createElement("div");

    const loadingImage = document.createElement("img");

    loadingImage.setAttribute("src", "pdf-loading.svg");
    const textLayer = isRenderText ? document.createElement("div") : null;
    if (textLayer)
    {
        pageLayer.appendChild(textLayer);
        textLayer.className = "textLayer";
    }
    pageLayer.className = "pageLayer";
    cavasLayer.className = "loading_canvasWrapper";

    pageLayer.setAttribute("data-pageIdx", `${pageNum}`);
    pageLayer.setAttribute("id", `page-${pageNum}`);
    pageLayer.setAttribute("data-pageLoad", `false`);

    drawLayer.className = "drawLayer";
    drawLayer.setAttribute("data-pageIdx", `${pageNum}`);
    drawLayer.setAttribute("id", `draw-${pageNum}`);

    if (waterMarkText)
    {
        const waterMarkLayer = document.createElement("div");
        waterMarkLayer.className = "waterMarkLayer";
        drawLayer.appendChild(waterMarkLayer);
    }

    pageLayer.appendChild(drawLayer);

    container.appendChild(pageLayer);
    cavasLayer.appendChild(canvas);
    pageLayer.appendChild(cavasLayer);
    loadingLayer.appendChild(loadingImage);
    loadingLayer.className = "loading";
    cavasLayer.appendChild(loadingLayer);

    const page = await pdf.getPage(pageNum);
    const viewport = page.getViewport({
        scale: scale
        ,rotation:rotate|0
    })

    canvas.width = viewport.width;
    canvas.height = viewport.height;

    const context = canvas.getContext("2d");
    if (!context) return;


    if(pageNum <= 3)
    {
        const isLoad = pageLayer.getAttribute("data-pageLoad") === "true" ? true : false;
        if(!isLoad)
        {
            pageLayer.setAttribute("data-pageLoad", `true`);
            await renderPage(page, context, viewport, textLayer).finally(() => {
                cavasLayer.className = "canvasWrapper";
                if (loadingImage && cavasLayer.contains(loadingLayer)) {
                    cavasLayer.removeChild(loadingLayer);
                }
            });
        }
    }
}



async  function renderPage(page:PDFPageProxy, context:CanvasRenderingContext2D, viewport:PageViewport, textLayer:HTMLDivElement|null)
{
    const renderContext = {
        canvasContext: context,
        viewport: viewport,
    };

    await page.render(renderContext).promise;

    if (textLayer)
    {
        page.getTextContent().then(textContent => {
            const txtLayer = renderTextLayer(
                {
                    textContentSource: textContent,
                    container: textLayer,
                    viewport: viewport,
                    isOffscreenCanvasSupported:true,

                }
            ).promise;
        }).finally(()=>{
            const parent = textLayer.parentElement;
            if (parent != null)
            {
                const drawLayer = parent.querySelector(".drawLayer");
                const pageStyle = textLayer.getAttribute("style");
                if (drawLayer && pageStyle)
                {
                    drawLayer.setAttribute("style", pageStyle);
                }

            }

        });
    }

}

export const PDFViewer = (props: PdfViewerProps) => {
    const { fileUrl , scale, renderText, downloadFileUrl
        , waterMarkText, fileName} = props;

    const [modalVisible, setModalVisible] = useState<boolean>(false);
    const downloadUrl = downloadFileUrl || fileUrl;
    const fileTitle= fileName||fileUrl;
    const [threshold, setThreshold] = useState<number>(0.7);
    const [scaleValue, setScaleValue] = useState<number>(scale || 1.5);
    const [currentPage, setCurrentPage] = useState<number>(1);
    const [totalPage, setTotalPage] = useState<number>(0);

    const rightClickCountRef = useRef(0);
    const leftClickCountRef = useRef(0);

    const [observer, setObserver] = useState<IntersectionObserver>();

    const [calcScaleValue, setCalcScaleValue] = useState(scaleValue);
    const timerRef = useRef<NodeJS.Timeout | null>(null);
    const timerClickRef = useRef<NodeJS.Timeout | null>(null);

    const [pdfDocument, setPdfDocument] = useState<PDFDocumentProxy>();


    const [modalTitle, setModalTitle] = useState<string>();

    const [progressVisible, setProgressVisible] = useState<boolean>(false);
    const [procPercent, setProcPercent] = useState<number>(0);

    const [passwordVisible, setPasswordVisible] = useState<boolean>(false);
    const [pdfPassword, setPdfPassword] = useState<string>("");
    const [pdfErrorMsg, setPdfErrorMsg] = useState<string>("");


    const waterMarkCanvasRef = useRef<HTMLCanvasElement>(null);

    const   isRenderText = renderText||false;

    const containerRef = useRef<HTMLDivElement>(null);

    const items:MenuProps['items'] = [
        {
            key: 'ACTUAL_SIZE',
            label: '실제크기',
        },
        {
            key: 'WIDTH_FIT',
            label: '가로에 맞추기',
        },
        {
            key: 'HEIGHT_FIT',
            label: '세로에 맞추기',
        },
        {
            key: '0.5',
            label: '50%',
        },
        {
            key: '0.75',
            label: '70%',
        },
        {
            key: '1.0',
            label: '100%',
        },
        {
            key: '1.25',
            label: '125%',
        },
        {
            key: '1.5',
            label: '150%',
        },
        {
            key: '2.0',
            label: '200%',
        },
        {
            key: '3.0',
            label: '300%',
        },
        {
            key: '4.0',
            label: '400%',
        },
    ];


    const handleRatioMenuClick: MenuProps['onClick'] = (e) => {
        const key:string = e.key;
        switch (key)
        {
            case 'ACTUAL_SIZE' :
                ZoomCtrl(1.0);
                break;
            case 'WIDTH_FIT' :
                ZoomCtrl(getWidthFitScale());
                break;
            case 'HEIGHT_FIT' :
                ZoomCtrl(getHeightFitScale());
                break;
            case '0.5' :
                ZoomCtrl(0.5);
                break;
            case '0.75' :
                ZoomCtrl(0.75);
                break;
            case '1.0' :
                ZoomCtrl(1.0);
                break;
            case '1.25' :
                ZoomCtrl(1.25);
                break;
            case '1.5' :
                ZoomCtrl(1.5);
                break;
            case '2.0' :
                ZoomCtrl(2.0);
                break;
            case '3.0' :
                ZoomCtrl(3.0);
                break;
            case '4.0' :
                ZoomCtrl(4.0);
                break;
            default:
                break;
        }
    };

    function calcThreshold(stdScaleValue:number) :number
    {
        if (0.5 >= stdScaleValue )
        {
            return 1.0;
        }
        else if (0.75 >= stdScaleValue && 1.0 < stdScaleValue)
        {
            return 0.9;
        }
        else if (1.0 >= stdScaleValue && 1.25 < stdScaleValue)
        {
            return 0.8;
        }
        else if (1.25 >= stdScaleValue && 1.5 < stdScaleValue)
        {
            return 0.7;
        }
        else if (1.5 >= stdScaleValue && 1.75 < stdScaleValue)
        {
            return 0.6;
        }
        else if (1.75 >= stdScaleValue && 2.0 < stdScaleValue)
        {
            return 0.5;
        }
        else if (2.0 >= stdScaleValue && 3.0 < stdScaleValue)
        {
            return 0.4;
        }
        else if (4.0 >= stdScaleValue )
        {
            return 0.3;
        }
        else
        {
            return 0.65
        }
    }

    const raioMenuProps = {
        items,
        onClick: handleRatioMenuClick,
    };

    function enterFullScreen(elementId: string): void {
        const element = document.getElementById(elementId) as HTMLElement & {
            requestFullscreen?: () => Promise<void>;
            webkitRequestFullscreen?: () => Promise<void>;
            mozRequestFullScreen?: () => Promise<void>;
            msRequestFullscreen?: () => Promise<void>;
        };

        if (!element) {
            console.error(`Element with id ${elementId} not found.`);
            return;
        }

        const onFullScreenEntered = () => {
            // 여기에 원하는 로직을 추가하세요.
            console.log("전체 화면 모드에 진입하였습니다.");
            ZoomCtrl(getWindowHeightFitScale());
            // 이벤트 리스너 제거
            document.removeEventListener('fullscreenchange', onFullScreenEntered);
        };

        // 이벤트 리스너 추가
        document.addEventListener('fullscreenchange', onFullScreenEntered);

        if (element.requestFullscreen) {
            element.requestFullscreen();
        } else if (element.webkitRequestFullscreen) {
            element.webkitRequestFullscreen();
        } else if (element.mozRequestFullScreen) {
            element.mozRequestFullScreen();
        } else if (element.msRequestFullscreen) {
            element.msRequestFullscreen();
        } else {
            console.error("Fullscreen API is not supported.");
        }
    }


    function scrollToDiv(pageNum:number) {
        const divId = `page-${pageNum}`;
        const element = document.getElementById(divId);
        if (element) {
            element.scrollIntoView({ behavior: 'smooth' });
        } else {
            console.error(`Element with id ${divId} not found.`);
        }
    }

    function movePage(pageNum:number)
    {
        if(pageNum < 1)
        {
            pageNum = 1;
        }
        else if(pageNum > totalPage)
        {
            pageNum = totalPage;
        }
        scrollToDiv(pageNum);
        return pageNum;
    }

    function getWidthFitScale()
    {
        const parentObj = document.getElementById("pdf_content");
        if(parentObj)
        {
            const parentWidth = parentObj.offsetWidth;
            console.log("부모 : " + parentWidth);
            const pageLayer = parentObj.querySelector(`.pageLayer[data-pageidx="${currentPage}"]`);
            if (pageLayer) {
                const canvas = pageLayer.querySelector('canvas');
                if (canvas)
                {
                    console.log("자식 : " + (canvas.width / calcScaleValue) );
                    return parentWidth / ((canvas.width / calcScaleValue) + 15) ;
                }
            }
        }
        return 0;
    }

    function getHeightFitScale()
    {
        const parentObj = document.getElementById("pdf_content");
        if(parentObj)
        {
            const parentHeight = parentObj.offsetHeight;
            const pageLayer = parentObj.querySelector(`.pageLayer[data-pageidx="${currentPage}"]`);
            if (pageLayer) {
                const canvas = pageLayer.querySelector('canvas');
                if (canvas)
                {
                    return parentHeight / ((canvas.height / calcScaleValue) + 30);
                }
            }
        }
        return 0;
    }

    function getWindowHeightFitScale()
    {
        const parentObj = document.getElementById("pdf_content");
        if(parentObj)
        {
            const pageLayer = parentObj.querySelector(`.pageLayer[data-pageidx="${currentPage}"]`);
            if (pageLayer) {
                const canvas = pageLayer.querySelector('canvas');
                if (canvas)
                {
                    return window.screen.height / ((canvas.height / calcScaleValue) + 15);
                }
            }
        }
        return 0;
    }

    function zoomIn(stdValue:number)
    {
        const maxZoom:number = 4.0;
        let calsZoom:number = stdValue + 0.25;

        if (calsZoom > maxZoom)
        {
            calsZoom = maxZoom;
        }
        return calsZoom;
    }

    function zoomOut(stdValue:number)
    {

        const minZoom:number = 0.5;
        let calsZoom:number = stdValue - 0.25;
        if (calsZoom < minZoom)
        {
            calsZoom = minZoom;
        }
        return calsZoom;

    }

    function drawLoadingPage(pageLayer:Element, isLoadingIcon:boolean)
    {
        pageLayer.setAttribute("data-pageLoad", "false");
        const cavasLayer = pageLayer.querySelector('.canvasWrapper') as HTMLDivElement;
        if (cavasLayer)
        {
            cavasLayer.className = "loading_canvasWrapper";

            if (isLoadingIcon)
            {
                const loadingLayer = document.createElement("div");
                const loadingImage = document.createElement("img");
                loadingImage.setAttribute("src", "pdf-loading.svg");

                loadingLayer.appendChild(loadingImage);
                loadingLayer.className = "loading";
                cavasLayer.appendChild(loadingLayer);
            }
        }
    }

    function drawLayerShowNHide(isShow:boolean)
    {
        if (containerRef.current)
        {
            const drawLayers = containerRef.current.querySelectorAll(".drawLayer");
            drawLayers.forEach((layer) => {
                if (!isShow)
                {
                    (layer as HTMLElement).style.display = 'none';
                }
                else
                {
                    (layer as HTMLElement).style.display = 'block';
                }
            });
        }

    }

    const ZoomCtrl = (calcZoom:number) => {

        if(calcZoom === calcScaleValue)
        {
            return;
        }
        if (observer)
        {
            observer.disconnect();
        }

        console.log("cal : " + calcZoom);
        console.log("calsc : " + calcScaleValue);
        console.log("cur : " + currentPage);


        const targetPageIdx = currentPage;
        const startIdx = Math.max(1, targetPageIdx - 3);
        const endIdx = targetPageIdx + 3;

        if (containerRef.current)
        {
            drawLayerShowNHide(false);
            setCalcScaleValue(calcZoom);

            const pdfViewer = containerRef.current;

            for (let i = 1; i <= totalPage; i++) {
                const pageLayer = pdfViewer.querySelector(`.pageLayer[data-pageidx="${i}"]`);
                if (pageLayer) {
                    const canvas = pageLayer.querySelector('canvas');
                    if (canvas) {
                        if ( i >= startIdx && i <= endIdx)
                        {
                            const tempCanvas = document.createElement('canvas');
                            const tempCtx = tempCanvas.getContext('2d');
                            if (!tempCtx) {
                                console.error("Failed to get 2d context from tempCanvas.");
                                return;
                            }
                            tempCanvas.width = canvas.width;
                            tempCanvas.height = canvas.height;
                            tempCtx.drawImage(canvas, 0, 0);
                            canvas.width = (canvas.width / calcScaleValue) * calcZoom;
                            canvas.height = (canvas.height / calcScaleValue) * calcZoom;

                            const ctx = canvas.getContext('2d')!;
                            ctx.drawImage(tempCanvas, 0, 0, tempCanvas.width, tempCanvas.height, 0, 0, canvas.width, canvas.height);
                        }
                        else
                        {
                            drawLoadingPage(pageLayer, true);
                            canvas.width = (canvas.width / calcScaleValue) * calcZoom;
                            canvas.height = (canvas.height / calcScaleValue) * calcZoom;
                        }

                        console.log("can : " + canvas.width);
                    }
                }
            }
        }

        if (timerRef.current) {
            clearTimeout(timerRef.current);
        }

        timerRef.current = setTimeout(() => {
            if (containerRef.current) {
                setCalcScaleValue(calcZoom);

                const pdfViewer = containerRef.current;

                for (let i = startIdx; i <= endIdx; i++) {
                    const pageLayer = pdfViewer.querySelector(`.pageLayer[data-pageidx="${i}"]`);
                    if (pageLayer) {
                        drawLoadingPage(pageLayer, false);
                    }
                }
            }

            const container = containerRef.current;
            container!.style.setProperty('--scale-factor', `${calcZoom}`); // 원하는 값으로 설정

            setScaleValue(calcZoom);
            setThreshold(calcThreshold(calcZoom));

            console.log("타임 : " + calcZoom);
        }, 500);
    }

    const observerOptions = {
        root: null,
        rootMargin: '0px 0px 30px 0px',
        threshold: threshold,
    }

    function createObserver(pdfDocument:PDFDocumentProxy)
    {
        if (observer)
        {
            observer.disconnect();
        }

        const newObserver = new IntersectionObserver((entries, observer) => {
            entries.forEach(async entry => {
                // 관찰 대상이 viewport 안에 들어온 경우 image 로드
                if (entry.isIntersecting) {
                    const pageLayer = entry.target;
                    const pageIdx: number = Number(pageLayer.getAttribute("data-pageidx"));
                    setCurrentPage(pageIdx);
                    await drawPdfPage(pdfDocument, pageLayer);
                }
            })
        }, observerOptions);

        setObserver(newObserver);

        const pdfPages = document.querySelectorAll('.pageLayer');
        pdfPages.forEach((pdfPage) => {
            newObserver.observe(pdfPage);
        })

        return () => {
            newObserver.disconnect();
        };
    }

    async function drawPdfPage(pdfDocument:PDFDocumentProxy, pageLayer: Element) {

        console.log(scaleValue);
        if (pdfDocument) {
            const pageIdx: number = Number(pageLayer.getAttribute("data-pageidx"));
            const cavasLayer = pageLayer.querySelector('.loading_canvasWrapper') as HTMLDivElement;
            const isLoad = pageLayer.getAttribute("data-pageLoad") === "true" ? true : false;

            if (cavasLayer && !isLoad) {
                pageLayer.setAttribute("data-pageLoad", `true`);
                const page = await pdfDocument.getPage(pageIdx);
                const textLayer = pageLayer.querySelector('.textLayer') as HTMLDivElement;
                const canvas = pageLayer.querySelector('canvas');
                const loadingLayer = pageLayer.querySelector('.loading');
                const context = canvas!.getContext("2d");
                if (!context) return;

                const viewport = page.getViewport({
                    scale: scaleValue
                    , rotation: 0
                })

                await renderPage(page, context, viewport, textLayer).finally(() => {
                    cavasLayer.className = "canvasWrapper";
                    if (loadingLayer && cavasLayer.contains(loadingLayer)) {
                        cavasLayer.removeChild(loadingLayer);
                    }
                });
            }
        }

    }

    async function runZoom() {
        if (containerRef.current && pdfDocument) {

            const pdfViewer = containerRef.current;
            const targetPageIdx = currentPage;
            const startIdx = Math.max(1, targetPageIdx - 3);
            const endIdx = targetPageIdx + 3;
            for (let i = startIdx; i <= endIdx; i++) {
                const pageLayer = pdfViewer.querySelector(`.pageLayer[data-pageidx="${i}"]`);
                if (pageLayer)
                {
                    await drawPdfPage(pdfDocument, pageLayer);
                }

            }

            createObserver(pdfDocument);
        }
    }

    async function loadPdfFromUrl() {
        const response = await fetch(fileUrl);
        if (!response.ok) {
            throw new Error(`Failed to fetch PDF from ${fileUrl}. Status: ${response.statusText}`);
        }
        const pdfBytes = new Uint8Array(await response.arrayBuffer());
        return pdfBytes;
    }

    async function getPdfBlob() {
        const warterMark = document.querySelector("#draw-1");
        if (warterMark != null && pdfDocument) {
            const waterMarkCanvas = await html2canvas(warterMark as HTMLElement, {
                backgroundColor: null,
            });
            //패스워드가 있으면 이미지를 만들고 없으면 기존거에 워터마크만 추가한다.
            const isSecurity = pdfPassword.length > 0;
            let pdfDoc:PDFDocument = isSecurity ? await PDFDocument.create() : await PDFDocument.load(await pdfDocument.getData());
            const waterMarkData = waterMarkCanvas.toDataURL("image/png");
            const waterMarkImage = pdfDoc.embedPng(waterMarkData);

            for (let i=1; i<=totalPage; i++)
            {
                setProcPercent(calculateProgress(i, totalPage, 100));
                let pdfPage:PDFPage|null = null;
                if (isSecurity)
                {
                    const page = await pdfDocument.getPage(i);
                    const viewport = page.getViewport({ scale: 2.0 });

                    const canvas = document.createElement('canvas');
                    const context = canvas.getContext('2d');
                    canvas.height = viewport.height;
                    canvas.width = viewport.width;

                    if (context && viewport) {
                        const renderContext = {
                            canvasContext: context,
                            viewport: viewport
                        };
                        await page.render(renderContext).promise;
                        pdfPage = pdfDoc.addPage([viewport.width, viewport.height]);
                        const pdfPageIamge = pdfDoc.embedJpg(canvas.toDataURL("image/jpeg"));
                        pdfPage.drawImage(await pdfPageIamge, {
                            x: 0,
                            y: 0,
                            width: viewport.width,
                            height: viewport.height
                        });
                    }

                }
                else
                {
                    pdfPage = pdfDoc.getPages()[i-1];
                }

                //워터마크 삽입
                if (pdfPage && waterMarkImage)
                {
                    pdfPage.drawImage(await waterMarkImage, {
                        x: 0,
                        y: 0,
                        width: pdfPage.getWidth(),
                        height: pdfPage.getHeight(),
                    });
                }
            }

            const modifiedPdfBytes = await pdfDoc.save();

            setProcPercent(100);
            const blob = new Blob([modifiedPdfBytes], {type: 'application/pdf'});
            return blob;

        }

        return null;
    }


    const downloadPdfDocument = async () => {

        const blob = await getPdfBlob();
        if (blob)
        {
            const pdfUrl = URL.createObjectURL(blob);
            const link = document.createElement('a');
            link.href = pdfUrl;
            link.download = 'overlayed.pdf';
            link.click();

            URL.revokeObjectURL(pdfUrl);

            hideModal();

        }
    };

    const printPdfDocument = async () => {

        const blob = await getPdfBlob();
        if (blob)
        {
            const pdfUrl = URL.createObjectURL(blob);
            const printIframe = document.getElementById('printFrame') as HTMLIFrameElement;

            printIframe.src = pdfUrl;
            const printWindow = printIframe.contentWindow;
            if (printWindow) {
                printIframe.onload = function () {
                    setTimeout(function () {
                        printWindow.print();
                        hideModal();
                        URL.revokeObjectURL(pdfUrl);
                    }, 500);
                };
            }
        }
    };

    function calculateProgress(currentPage:number, totalPage:number, totalPercent:number) {
        const progress = (currentPage / totalPage) * totalPercent;
        console.log(progress);
        return Math.min(Math.round(progress), totalPercent);  // 진행률이 100%를 초과하지 않도록 합니다.
    }

    function showModal(revModalTitle:string, isProgress:boolean)
    {
        if (isProgress)
        {
            setProgressVisible(true);
        }
        setProcPercent(0);
        setModalTitle(revModalTitle);
        setModalVisible(true);
    }

    function hideModal()
    {
        setPdfErrorMsg("");
        setModalVisible(false);
        setModalTitle("");
        setProcPercent(0);
        setProgressVisible(false);
        setPasswordVisible(false);
    }

    function PrevPage()
    {
        const movePageNum = currentPage-1;
        setCurrentPage(movePage(movePageNum < 1 ? 1: movePageNum ));
    }

    function NextPage()
    {
        const movePageNum = currentPage+1;
        setCurrentPage(movePage(movePageNum > totalPage ? totalPage : movePageNum ));
    }


    const handleDoubleClick = (event:React.MouseEvent<HTMLDivElement, MouseEvent>) => {
        event.preventDefault();

        leftClickCountRef.current += 1;

        if (leftClickCountRef.current === 1) {
            timerClickRef.current = setTimeout(() => {
                leftClickCountRef.current = 0; // 클릭 횟수 초기화
            }, 250);
        } else if (leftClickCountRef.current === 2) {
            if (timerClickRef.current) {
                clearTimeout(timerClickRef.current);
            }

            ZoomCtrl( zoomIn( calcScaleValue || scaleValue ) );
            leftClickCountRef.current = 0; // 클릭 횟수 초기화
        }
    };

    const handleRightClick = (event:React.MouseEvent<HTMLDivElement, MouseEvent>) => {
        event.preventDefault();

        rightClickCountRef.current += 1;

        if (rightClickCountRef.current === 1) {
            timerClickRef.current = setTimeout(() => {
                rightClickCountRef.current = 0; // 클릭 횟수 초기화
            }, 250);
        } else if (rightClickCountRef.current === 2) {
            if (timerClickRef.current) {
                clearTimeout(timerClickRef.current);
            }
            ZoomCtrl( zoomOut( calcScaleValue || scaleValue ) );
            rightClickCountRef.current = 0; // 클릭 횟수 초기화
        }
    };

    const handlePasswordSubmit = () => {
        loadPdf(pdfPassword).then(r => { });

    };



    useEffect(() => {
        if (waterMarkText && waterMarkCanvasRef.current) {
            const canvas = waterMarkCanvasRef.current;
            const ctx = canvas.getContext('2d');
            const fontSize = 70 * scaleValue;
            const padding = fontSize;
            if (ctx) {

                ctx.font = `${fontSize}px Arial`;
                const textWidth = ctx.measureText(waterMarkText).width;
                const textHeight = fontSize; // 이 값은 폰트 크기에 따라 조절하시길 바랍니다.

                canvas.width = textWidth + padding;
                canvas.height = textHeight + padding * 2;

                ctx.font = `${fontSize}px Arial`; // 캔버스 크기가 변경되면 폰트 설정도 초기화되므로 다시 설정해야 합니다.
                ctx.fillStyle = 'rgba(0, 0, 0, 0.10)';
                ctx.fillText(waterMarkText, 0, textHeight - 5); // y 좌표를 조절하여 텍스트가 캔버스 내에 잘 들어가도록 합니다.

                //setWaterMarkImgURl(canvas.toDataURL('image/png'));
                const waterMarkImgURl = canvas.toDataURL('image/png');
                if(waterMarkImgURl)
                {
                    const style = document.createElement('style');
                    style.innerHTML = `
                        .pdfViewer .waterMarkLayer::before {
                            content: "";
                            position: absolute;
                            top: 0px;
                            left: 0px;
                            width: 200%;
                            height: 200%;
                            background-image: url(${waterMarkImgURl});
                            background-repeat: repeat;
                            transform: rotate(-45deg);
                            background-color: transparent;
                        }`;
                    document.head.appendChild(style);
                }
            }
        }
    }, [waterMarkText, scaleValue]);


    const loadPdf = async (password: string | null | undefined) => {
        console.log("PDFViewer component rendered");

        const container = containerRef.current;

        if (!container) return;

        // Clear the container's contents whenever fileUrl changes
        container.innerHTML = "";

        const loadOption: any = {
            url: fileUrl,
            cMapUrl: `https://unpkg.com/pdfjs-dist@${PdfjsVersion}/cmaps/`,
            cMapPacked: true,
            enableXfa: true,
        };

        if (password) {
            loadOption.password = password;
        }

        let isError = false;

        try {
            const pdfDocumentProxy: PDFDocumentProxy = await getDocument(loadOption).promise;

            setPdfDocument(pdfDocumentProxy);
            setTotalPage(pdfDocumentProxy.numPages);

            container.style.setProperty('--scale-factor', `${scaleValue}`); // 원하는 값으로 설정

            for (let pageNum = 1; pageNum <= pdfDocumentProxy.numPages; pageNum++) {
                await loadPage(pdfDocumentProxy, pageNum, scaleValue, 0, container, isRenderText, waterMarkText);
            }

            createObserver(pdfDocumentProxy);

        } catch (error:any) {
            isError = true
            if (error.name === 'PasswordException' && !password) {
                showModal("보안 PDF", false);
                setPasswordVisible(true);
            }
            else if (error.name === 'PasswordException' && error.message === 'Incorrect Password' && password) {

                setPdfErrorMsg("PDF 암호가 잘못되었습니다.");
                showModal("보안 PDF", false);
                setPasswordVisible(true);
            }
            else {
                console.error(error);
            }
        }
        finally {
            if (!isError && password)
                hideModal();
        }
    };


    useEffect(() => {

        setTotalPage(0);
        setCurrentPage(1);
        setPdfErrorMsg("");
        setPdfPassword("");

        loadPdf(null);

    }, [fileUrl]);



    useEffect(() => {
        runZoom().then().finally( () =>{
            drawLayerShowNHide(true);
        });
    }, [ scaleValue ]);


    useEffect(() => {
        const handleKeyDown = (event:KeyboardEvent) => {

            switch (event.key) {
                case 'PageUp':
                    PrevPage();
                    console.log("up");
                    event.preventDefault();  // 기본 동작 방지
                    break;
                case 'PageDown':
                    NextPage();
                    console.log("down");
                    event.preventDefault();  // 기본 동작 방지
                    break;
                case '+':
                    ZoomCtrl( zoomIn( calcScaleValue || scaleValue ) );
                    break;
                case '-':
                    ZoomCtrl( zoomOut( calcScaleValue || scaleValue ) );
                    break;
                default:
                    break;
            }
        };


        window.addEventListener('keydown', handleKeyDown);

        return () => {
            window.removeEventListener('keydown', handleKeyDown);
        };
    }, [currentPage, scaleValue, calcScaleValue, totalPage]);  // currentPage가 변경될 때마다 이벤트 리스너 갱신

    return (

        <div
            style={{
                width: '100%',
            }}
        >
            <nav style={{
                margin:'0px 0px 4px 0px',
                padding:'9px 8px 9px 0px',
                height: '50px',
                display:'flex',
                justifyContent: "space-between",
                alignItems:'center',
                borderRadius: "8px", // 라운드 처리 추가
                border: '1px solid #dadada',

                background: "white",
            }}>
                <div style={{ width:'34%', marginLeft: '8px' }}>

                    <Space.Compact  style={{
                        width:'100%',
                        justifyContent:'left',
                        alignItems:'center',
                        display:'flex'
                    }} block>
                            <Tooltip title="이전페이지" arrow={false}>
                                <Button type="primary" icon={<CaretLeftOutlined />} onClick={() => {
                                    PrevPage();
                                }}/>
                            </Tooltip>
                                <Input
                                    type="number"
                                    style={{
                                    marginLeft : "10px",
                                    marginRight : "5px",
                                    width : "65px"
                                }} size="small" value={currentPage}
                                    onChange={e => setCurrentPage(Number(e.target.value))}
                                    onKeyDown={(e) => {
                                        if (e.key === 'Enter') {
                                            setCurrentPage(movePage(currentPage));
                                        }
                                    }}
                                />
                                /
                                <Input style={{
                                    marginLeft : "5px",
                                    marginRight : "10px",
                                    width : "40px"
                                }} size="small" value={totalPage} readOnly/>
                            <Tooltip title="다음페이지" arrow={false}>
                                <Button type="primary" icon={<CaretRightOutlined />} onClick={() => {

                                    NextPage();

                                }}/>
                            </Tooltip>



                    </Space.Compact>


                </div>
                <div style={{ width:'33%', textAlign: 'center', flexGrow: 1 }}>
                    <Space.Compact  style={{
                        width:'100%',
                        justifyContent:'center',
                    }} block>
                            <Tooltip title="확대" arrow={false}>
                                <Button type="primary" icon={<ZoomInOutlined />} onClick={() => {

                                    ZoomCtrl( zoomIn( calcScaleValue || scaleValue ) );
                                    //zoonIn();
                                }}/>
                            </Tooltip>

                        <Tooltip title="비율로보기">
                            <Dropdown
                                placement="bottomCenter"
                                menu={raioMenuProps}
                            >
                                <Button  type="primary" icon={<PercentageOutlined />}/>
                            </Dropdown  >
                        </Tooltip>
                            <Tooltip title="축소" arrow={false}>
                                <Button type="primary" icon={<ZoomOutOutlined />} onClick={() => {
                                    //zoonOut();
                                    ZoomCtrl( zoomOut( calcScaleValue || scaleValue ) );
                                }}/>
                            </Tooltip>
                    </Space.Compact>
                </div>
                <div style={{ width:'33%',  marginRight: '8px',textAlign: 'right' }}>
                    <Space.Compact  style={{
                        width:'100%',
                        justifyContent:'flex-end',
                    }} block>
                            <Tooltip title="전체화면" arrow={false}>
                                <Button type="primary" icon={<FullscreenOutlined />} onClick={() => {
                                    enterFullScreen("pdf_content");
                                }}/>
                            </Tooltip>
                        <Tooltip title="다운로드" arrow={false}>
                            <Button type="primary" icon={<DownloadOutlined />} onClick={() => {
                                showModal("다운로드 준비중..", true);
                                downloadPdfDocument().finally(() => {
                                });
                            }
                            }/>
                        </Tooltip>
                        <Tooltip title="인쇄" arrow={false}>
                                <Button type="primary" icon={<PrinterOutlined />} onClick={() => {
                                    showModal("인쇄 준비중..", true);
                                    printPdfDocument().finally(() => {
                                    });
                                }}/>
                        </Tooltip>
                    </Space.Compact>
                </div>
            </nav>
            <div
                id="pdf_content"
                style={{
                    border: '1px solid rgba(0, 0, 0, 0.1)',
                    display: 'flex',
                    height: 'calc( 100vh - 120px )',
                }}

            >
                <div
                    style={{
                        width:'100%',
                        overflow:"auto"
                    }}
                >
                    <div onClick={handleDoubleClick}
                         onContextMenu={handleRightClick}
                         className="pdfViewer"   ref={containerRef} />
                </div>
                <canvas ref={waterMarkCanvasRef} style={{ display: 'none' }} />
                <iframe id="printFrame"/>

                <Modal
                    centered
                    open={modalVisible}
                    title={modalTitle}
                    footer={null}
                    closable={false}
                >
                    {progressVisible && <Progress percent={procPercent} status="active" />}
                    {
                        passwordVisible &&
                        <>
                            <div style={{
                                        fontWeight:"bold",
                                        marginLeft:"10px",
                                        marginBottom : "10px",
                                        color:"red"}}>{pdfErrorMsg}</div>
                            <Input
                                placeholder="문서가 비밀번호로 보호되고 있습니다. 비밀번호를 입력하세요."
                                type="password"
                                style={{
                                    margin : "0px",
                                    width : "100%",
                                    height : "35px"
                                }} size="small"
                                value={pdfPassword}
                                onChange={(e) => {setPdfPassword(e.target.value)}}
                                onKeyDown={(e) => {
                                    if (e.key === 'Enter') {
                                        handlePasswordSubmit();
                                    }
                                }}
                            />

                        </>

                    }


                </Modal>




            </div>
        </div>

        );

};
