import React, { forwardRef, useEffect, useState } from 'react';

import PageView from '../PageView';
import { ViewportType } from '../../constants/type';
import { scrollIntoView } from '../../helpers/utility';

import { Container, Wrapper } from './styled';

type Props = {
  totalPage: number;
  currentPage: number;
  viewport: ViewportType;
  pdf: any;
  rotation: number;
};
type Ref = HTMLDivElement;

const Viewer = forwardRef<Ref, Props>(({
  totalPage,
  currentPage,
  viewport,
  pdf,
  rotation,
}, ref) => {
  const [elements, setElement] = useState<React.ReactNode[]>([]);

  const getPdfPage = async (pageNum: number) => {
    const page = await pdf.getPage(pageNum);
    return page;
  };

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

    for(let i = 1; i <= totalPage; i++) {
      const component = (
        <PageView
          key={`page-${i}`}
          pageNum={i}
          renderingState={[1, 2, 3].includes(i) ? 'RENDERING' : 'LOADING'}
          viewport={viewport}
          getPage={() => getPdfPage(i) }
          rotation={rotation}
        />
      );
      pagesContent.push(component);
    }

    setElement(pagesContent);
  };

  const updatePages = () => {
    const renderingIndexQueue = [currentPage - 1 ,currentPage, currentPage + 1];
    let index = currentPage - 2;
    const end = currentPage + 2;

    while (true) {
      if (elements[index]) {
        const pageNum = index + 1;

        elements[index] = (
          <PageView
            key={`page-${pageNum}`}
            pageNum={pageNum}
            renderingState={renderingIndexQueue.includes(pageNum) ? 'RENDERING' : 'LOADING'}
            viewport={viewport}
            getPage={() => getPdfPage(pageNum)}
            rotation={rotation}
          />
        )
      }

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

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

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

        if (i === currentPage) {
          updatePages();
          scrollIntoView(ele);
        }
      }
    }
  }

  useEffect(() => {
    createPages();
  }, [totalPage]);

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

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

  return (
    <Container ref={ref}>
      <Wrapper width={rotation / 90 % 2 === 1 ? viewport.height : viewport.width}>
        {elements}
      </Wrapper>
    </Container>
  );
});

export default Viewer;
