import React, { FC, useRef, useState } from 'react';
import { GridContextProvider } from 'react-grid-dnd';
import { observer } from 'mobx-react-lite';
import { v4 as uuidv4 } from 'uuid';

import { Collapse, Select } from 'antd';

import styles from './DocumentMoveCollection.module.scss';

import { IDocument } from '../../../store/documents';
import useDragDocuments from './useDragDocuments';
import { collectionsToDocuments } from '../../../utils/commonHelpers';
import {
  getCollectionHeight,
  sortedCollectionToTwoDimensionalCollections,
} from '../utils';
import DndCollections from './DndCollections';
import useActiveKeys from './useActiveKeys';
import CollectionItem from './CollectionItem';
import useGalleryScrollFlip from '../hooks/useGalleryScrollFlip';
import {
  defaultSortBy,
  SortedCollection,
  SortType,
} from '../hooks/useCurrentDocument';
import DeleteDocumentModal from '../../DeleteDocumentModal';
import useStore from '../../../hooks/useStore';
import { LoadingStatus } from '../../../store/types';
import Loader from '../../Loader';
import DndActions from './DndActions';
import { toJS } from 'mobx';

const { Option } = Select;
const { Panel } = Collapse;

interface DocumentMoveCollectionProps {
  sortType: SortType;
  setSortType: (type: SortType) => void;
  sortedCollection: SortedCollection;
  currentDocument: IDocument;
  setPrevDocument: () => void;
  setNextDocument: () => void;
  setActiveCollectionAndIndex: (
    collectionUUID: string | null,
    index: number
  ) => void;
}

const DocumentMoveCollection: FC<DocumentMoveCollectionProps> = ({
  sortType,
  setSortType,
  sortedCollection,
  currentDocument,
  setPrevDocument,
  setNextDocument,
  setActiveCollectionAndIndex,
}) => {
  const { documentsStore } = useStore();

  const { handleDrag } = useDragDocuments();
  const { activeKeys, setActiveKeys } = useActiveKeys(
    sortType,
    (sortType === 'date'
      ? currentDocument.creationDate
      : currentDocument.documentType) || 'noType'
  );
  const containerRef = useGalleryScrollFlip({
    setPrevDocument,
    setNextDocument,
  });
  const [isDnd, setIsDnd] = useState(false);
  const [deleteModal, setDeleteModal] = useState<{
    documentMetadata: string;
  } | null>(null);

  const dndAction = useRef(false);

  const documents = collectionsToDocuments(
    sortedCollectionToTwoDimensionalCollections(sortedCollection)
  );

  const handleMouseDown = () => {
    dndAction.current = false;
    setIsDnd(true);
  };

  const handleMouseUp = (document: IDocument) => {
    setIsDnd(false);
    // when just click without dnd, it just set clicked item to "active"
    setTimeout(() => {
      if (!dndAction.current) {
        const collection = documents.filter(
          (doc) => doc.collectionUUID === document.collectionUUID
        );
        const documentIndex = collection.findIndex(
          (d) => d.filename === document.filename
        );
        setActiveCollectionAndIndex(document.collectionUUID, documentIndex);
      }
    }, 0);
  };

  const handleAllDocumentsMouseUp =
    (index: number) => () => {
      setIsDnd(false);
      setTimeout(() => {
        if (!dndAction.current) {
          setActiveCollectionAndIndex('', index);
        }
      }, 0);
    };

  const dndChange = (
    ...args: [
      sourceId: string,
      sourceIndex: number,
      targetIndex: number,
      targetId?: string | undefined
    ]
  ) => {
    dndAction.current = true;
    setIsDnd(false);
    if (args[3] === 'createNewCollection') {
      const sourceItem = documents.filter(
        (document) => document.collectionUUID === args[0]
      )[args[1]];
      (async () => {
        await documentsStore.documentToNewCollection({
          metadata: toJS(sourceItem).metadata,
          newCollectionUUID: uuidv4(),
        });
      })();
    } else if (args[3] === 'delete') {
      const sourceItem = documents.filter(
        (document) => document.collectionUUID === args[0]
      )[args[1]];
      setDeleteModal({ documentMetadata: sourceItem.metadata });
    } else {
      handleDrag(...args);
    }
  };

  return (
    <div ref={containerRef}>
      <Select
        className={styles.typeSelect}
        defaultValue={defaultSortBy}
        onSelect={setSortType}
      >
        <Option value="type">За типом</Option>
        <Option value="date">За датою</Option>
      </Select>

      <>
        {(documentsStore.documentToNewCollectionLoadingStatus ===
          LoadingStatus.LOADING ||
          documentsStore.editDocumentLoadingStatus ===
            LoadingStatus.LOADING) && (
          <div className={styles.loader}>
            <Loader />
          </div>
        )}
        <GridContextProvider onChange={dndChange}>
          <Collapse
            className={styles.collapse}
            activeKey={activeKeys}
            onChange={(keys) => typeof keys === 'object' && setActiveKeys(keys)}
          >
            <Panel className={styles.panel} header="Всі" key="all">
              <div
                style={getCollectionHeight(documents.length)}
                className={styles.collectionDropZone}
              >
                {documents.map((document, index) => (
                  <CollectionItem
                    key={document.filename}
                    draggable={false}
                    document={document}
                    currentDocument={currentDocument}
                    onMouseDown={handleMouseDown}
                    onMouseUp={handleAllDocumentsMouseUp(index)}
                  />
                ))}
              </div>
            </Panel>
            {Object.keys(sortedCollection).map((name) => (
              <Panel
                className={styles.panel}
                header={`${name === 'noType' ? 'Не мають типу' : name} (${
                  sortedCollection[name].length
                })`}
                key={name}
              >
                <DndCollections
                  collections={sortedCollection[name]}
                  sortType={sortType}
                  currentDocument={currentDocument}
                  onMouseDown={handleMouseDown}
                  onMouseUp={handleMouseUp}
                />
              </Panel>
            ))}
          </Collapse>
          {isDnd && <DndActions />}
        </GridContextProvider>
      </>

      <DeleteDocumentModal
        isOpen={!!deleteModal}
        metadata={deleteModal?.documentMetadata || ''}
        onClose={() => setDeleteModal(null)}
        onSuccess={() => setDeleteModal(null)}
      />
    </div>
  );
};

export default observer(DocumentMoveCollection);
