import React, {
  useEffect, useState, useRef,
} from 'react';
import _ from 'lodash';

import { AnnotationType, ScrollStateType } from '../constants/type';
import Page from '../components/Page';
import Viewer from '../components/Viewer';
import Annotation from './Annotation';
import { watchScroll } from '../helpers/utility';
import { getPdfPage } from '../helpers/pdf';

import useStore from '../store';

type Props = {
  scrollToUpdate: (state: ScrollStateType) => void;
};

const PdfPages: React.FunctionComponent<Props> = ({
  scrollToUpdate,
}: Props) => {
  const [elements, setElement] = useState<React.ReactNode[]>([]);
  const containerRef = useRef<HTMLDivElement>(null);
  const [{
    totalPage,
    currentPage,
    viewport,
    pdf,
    rotation,
    displayMode,
    annotations,
    scale,
  }] = useStore();

  const getAnnotations = (arr: AnnotationType[], pageNum: number): any[] => {
    const result: any[] = [];
    arr.forEach((ele: AnnotationType, index: number) => {
      const page = ele.obj_attr ? ele.obj_attr.page as number + 1 : 0;
      if (page === pageNum) {
        result.push(<Annotation key={`annotations_${pageNum + index}`} scale={scale} index={index} {...ele} />);
      }
    });
    return result;
  };

  const createPages = (): void => {
    const pagesContent: React.ReactNode[] = [];

    for (let i = 1; i <= totalPage; i += 1) {
      const annotationElements = getAnnotations(annotations, i);
      const component = (
        <Page
          key={`page-${i}`}
          pageNum={i}
          renderingState={_.range(1, 4).includes(i) ? 'RENDERING' : 'LOADING'}
          viewport={viewport}
          getPage={(): Promise<any> => getPdfPage(pdf, i)}
          rotation={rotation}
          annotations={annotationElements}
        />
      );
      pagesContent.push(component);
    }

    setElement(pagesContent);
  };

  const updatePages = (): void => {
    const renderingIndexQueue = _.range(currentPage - 1, currentPage + 2);
    let index = currentPage - 4;
    const end = currentPage + 3;

    while (currentPage) {
      if (elements[index]) {
        const pageNum = index + 1;
        const annotationElements = getAnnotations(annotations, pageNum);

        elements[index] = (
          <Page
            key={`page-${pageNum}`}
            pageNum={pageNum}
            renderingState={renderingIndexQueue.includes(pageNum) ? 'RENDERING' : 'LOADING'}
            viewport={viewport}
            getPage={(): Promise<any> => getPdfPage(pdf, pageNum)}
            rotation={rotation}
            annotations={annotationElements}
          />
        );
      }

      index += 1;
      if (index >= end) break;
    }

    if (elements.length) {
      setElement([...elements]);
    }
  };

  useEffect(() => {
    createPages();
    watchScroll(containerRef.current, scrollToUpdate);
  }, []);

  useEffect(() => {
    updatePages();
  }, [currentPage, viewport, rotation, annotations]);

  return (
    <Viewer
      ref={containerRef}
      viewport={viewport}
      rotation={rotation}
      displayMode={displayMode}
    >
      {elements}
    </Viewer>
  );
};

export default PdfPages;
