import React, {
  useEffect, useState, useRef, useCallback,
} from 'react';
import queryString from 'query-string';

import Icon from '../Icon';
import Drawer from '../Drawer';
import Typography from '../Typography';
import Item from '../AnnotationItem';
import {
  AnnotationType, ViewportType, ScrollStateType, PositionType,
} from '../../constants/type';

import { downloadFileWithUri, watchScroll } from '../../helpers/utility';
import { getAnnotationText } from '../../helpers/annotation';
import { Separator } from '../../global/otherStyled';
import {
  Container, Head, Body, IconWrapper,
} from '../../global/sidebarStyled';

type Props = {
  isActive?: boolean;
  close: () => void;
  annotations: AnnotationType[];
  viewport: ViewportType;
  scale: number;
  pdf: any;
};

const AnnotationsList: React.FunctionComponent<Props> = ({
  isActive = false,
  close,
  annotations,
  viewport,
  scale,
  pdf,
}: Props) => {
  const [renderQueue, setQueue] = useState<AnnotationType[]>([]);
  const containerRef = useRef<HTMLDivElement>(null);
  const innerRef = useRef<HTMLDivElement>(null);

  const handleExport = (): void => {
    const parsed = queryString.parse(window.location.search);
    const uri = `/api/v1/output.xfdf?f=${parsed.token}`;
    downloadFileWithUri('output.xfdf', uri);
  };

  const getText = async (page: number, position: PositionType[]): Promise<any> => {
    const text = await getAnnotationText({
      pdf,
      viewport,
      scale,
      page,
      coords: position,
    });
    return text;
  };

  const scrollUpdate = useCallback((state: ScrollStateType): void => {
    const innerHeight = innerRef.current?.offsetHeight || 0;
    const wrapperHeight = containerRef.current?.offsetHeight || 0;

    if (
      wrapperHeight + state.lastY >= innerHeight
      && renderQueue.length !== annotations.length
    ) {
      const start = renderQueue.length;
      const end = renderQueue.length + 10;
      const newQueue = [...renderQueue, ...annotations.slice(start, end)];
      setQueue(newQueue);
    }
  }, [renderQueue, annotations]);

  useEffect(() => {
    const state = watchScroll(containerRef.current, scrollUpdate);

    return (): void => {
      state.subscriber.unsubscribe();
    };
  }, [scrollUpdate]);

  useEffect(() => {
    if (isActive) {
      setQueue(annotations.slice(0, 10));
    }
  }, [isActive]);

  return (
    <Drawer anchor="right" open={isActive}>
      <Container>
        <Head>
          <IconWrapper>
            <Icon glyph="right-back" onClick={close} />
          </IconWrapper>
          <Separator />
          <IconWrapper>
            <Icon glyph="sort" />
          </IconWrapper>
          <IconWrapper onClick={handleExport}>
            <Icon glyph="annotation-export" />
          </IconWrapper>
          <IconWrapper>
            <Icon glyph="import" />
          </IconWrapper>
        </Head>
        <Body ref={containerRef}>
          <div ref={innerRef}>
            <Typography light align="left">
              {`${annotations.length} Annotations`}
            </Typography>
            {isActive && renderQueue.map((ele, index) => {
              const key = `annot_item_${index}`;
              const {
                obj_type,
                obj_attr: {
                  page,
                  bdcolor,
                  position,
                  transparency,
                },
              } = ele;
              const actualPage = page + 1;
              const prevPage = index > 0 ? annotations[index - 1].obj_attr.page + 1 : -1;
              return (
                <Item
                  key={key}
                  type={obj_type}
                  page={actualPage}
                  bdcolor={bdcolor}
                  transparency={transparency}
                  getText={(): Promise<any> => getText(actualPage, position)}
                  showPageNum={actualPage !== prevPage}
                />
              );
            })}
          </div>
        </Body>
      </Container>
    </Drawer>
  );
};

export default AnnotationsList;
