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

import { initialPdfFile, fetchXfdf } from '../apis';
import PdfPages from './PdfPages';
import { fetchPdf } from '../helpers/pdf';
import {
  parseAnnotationFromXml,
  parseFormElementFromXml,
} from '../helpers/annotation';
import { parseWatermarkFromXml } from '../helpers/watermark';

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

const PdfViewer: React.FC = () => {
  const [{ viewport, pdf, scale }, dispatch] = useStore();
  const {
    setTotalPage,
    setPdf,
    setProgress,
    setViewport,
    setCurrentPage,
    setInfo,
    addAnnots,
    changeScale,
    updateWatermark,
  } = useActions(dispatch);

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

  const getViewport = async (pdfEle: PdfType, s: number): Promise<void> => {
    if (!pdfEle) return;
    const page = await pdfEle.getPage(1);

    if (!page) return;
    const iViewport = page.getViewport({ scale: s });

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

  const getXfdfFile = (token: string): void => {
    fetchXfdf(token)
      .then((xfdf) => {
        const annotations = parseAnnotationFromXml(xfdf);
        const forms = parseFormElementFromXml(xfdf);
        const watermark = parseWatermarkFromXml(xfdf);

        if (watermark.obj_attr.type) {
          addAnnots([...annotations, ...forms, watermark], false);
          updateWatermark(watermark.obj_attr);
        } else {
          addAnnots([...annotations, ...forms], false);
        }
      })
      .catch((error) => {
        console.log(error);
      });
  };

  const pdfStarter = async (): Promise<void> => {
    const parsed = queryString.parse(window.location.search);

    if (parsed.token) {
      const token = parsed.token as string;
      const result = (await initialPdfFile(token)) as {
        data: { transaction_id: string; size: number };
      };

      getXfdfFile(token);
      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),
      );

      if (!iPdf) return;
      setTotalPage(iPdf.numPages);
      setPdf(iPdf);

      const page = (await iPdf.getPage(1)) as PdfPageType;
      if (!page) return;
      const iViewport = page.getViewport({ scale: 1 });

      iViewport.width = Math.round(iViewport.width);
      iViewport.height = Math.round(iViewport.height);
      const screenWidth = window.document.body.offsetWidth - 286;
      const originPdfWidth = iViewport.width;

      const rate = (screenWidth / originPdfWidth).toFixed(2);
      changeScale(rate);
    }
  };

  const scrollToUpdate = (state: ScrollStateType): void => {
    const ele: HTMLDivElement = document.getElementById(
      'page_1',
    ) as HTMLDivElement;
    const pageNum = Math.round(
      (state.lastY + ele.offsetHeight / 1.4) / (ele.offsetHeight + 50),
    );

    setCurrentPage(pageNum);
  };

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

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

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

export default PdfViewer;
