import React, { useEffect, useRef } from 'react';
import queryString from 'query-string';
import config from '../config';
import apiPath from '../constants/apiPath';

import { initialPdfFile } from '../apis';
import PdfPages from './PdfPages';
import { fetchPdf } from '../helpers/pdf';
import { ProgressType, ScrollStateType } from '../constants/type';
import { scrollIntoView } from '../helpers/utility';
import { parseAnnotationFromXml, fetchXfdf } from '../helpers/annotation';

import useActions from '../actions';
import useStore from '../store';

const PdfViewer: React.FunctionComponent = () => {
  const [{
    viewport,
    pdf,
    scale,
    currentPage,
    totalPage,
  }, dispatch] = useStore();
  const {
    setTotalPage,
    setPdf,
    setProgress,
    setViewport,
    setCurrentPage,
    setInfo,
    addAnnotation,
    changeScale,
  } = useActions(dispatch);
  const currentPageRef = useRef(0);

  const setLoadingProgress = (totalSize: number) => (progress: ProgressType): void => {
    setProgress({
      total: totalSize,
      loaded: progress.loaded,
    });
  };

  const getViewport = async (pdfEle: any, s: number): Promise<any> => {
    const page = await pdfEle.getPage(1);
    const iViewport = page.getViewport({ scale: s });

    iViewport.width = Math.round(iViewport.width);
    iViewport.height = Math.round(iViewport.height);
    setViewport(iViewport);
  };

  const pdfGenerator = async (): Promise<any> => {
    const parsed = queryString.parse(window.location.search);
    const result = await initialPdfFile(parsed.token as string);

    fetchXfdf(parsed.token as string).then((res) => {
      if (res) {
        const annot = parseAnnotationFromXml(res);
        addAnnotation(annot, false);
      }
    });

    if (result.data) {
      setInfo({
        token: parsed.token,
        id: result.data.transaction_id,
      });

      const iPdf = await fetchPdf(
        `${config.API_HOST}${apiPath.getOriginalPdfFile}?transaction_id=${result.data.transaction_id}`,
        setLoadingProgress(result.data.size),
      );

      setTotalPage(iPdf.numPages);
      setPdf(iPdf);

      const page = await iPdf.getPage(1);
      const iViewport = page.getViewport({ scale: 1 });

      iViewport.width = Math.round(iViewport.width);
      iViewport.height = Math.round(iViewport.height);
      const screenwidth = window.screen.width - 200;
      const originPdfWidth = iViewport.width / 1;
      const rate = screenwidth / originPdfWidth;
      changeScale(rate);
    }
  };

  const changePdfContainerScale = (): void => {
    for (let i = 1; i <= totalPage; i += 1) {
      const ele: HTMLDivElement = document.getElementById(`page_${i}`) as HTMLDivElement;
      if (ele) {
        ele.style.width = `${viewport.width}px`;
        ele.style.height = `${viewport.height}px`;

        if (i === currentPageRef.current) {
          scrollIntoView(ele);
        }
      }
    }
  };

  const scrollToUpdate = (state: ScrollStateType): void => {
    const ele: HTMLDivElement = document.getElementById('page_1') as HTMLDivElement;
    const page = Math.round((state.lastY + ele.offsetHeight / 1.4) / (ele.offsetHeight + 40));
    if (page !== currentPageRef.current) {
      setCurrentPage(page);
    }
  };

  useEffect(() => {
    pdfGenerator();
  }, []);

  useEffect(() => {
    currentPageRef.current = currentPage;
  }, [currentPage]);

  useEffect(() => {
    if (pdf) {
      changePdfContainerScale();
    }
  }, [viewport]);

  useEffect(() => {
    if (pdf) {
      getViewport(pdf, scale);
    }
  }, [scale]);

  return (
    viewport.width ? (
      <PdfPages scrollToUpdate={scrollToUpdate} />
    ) : null
  );
};

export default PdfViewer;
