import { useEffect, useState } from 'react';
import { Box, IconButton } from '@mui/material';
import {
  Add as AddIcon,
  Check as CheckIcon,
  Edit as EditIcon,
} from '@mui/icons-material';
import { styled } from '@mui/material/styles';
import EventEmitter from 'events';

import API_BASE_URL from '../../lib/consts/API_BASE_URL';
import { BLUE, PURPLE, RED } from '../../lib/consts/DEFAULT_THEME';
import ICON_BUTTON_STYLE from '../../lib/consts/ICON_BUTTON_STYLE';

import { Panel } from '../Panels';
import Spinner from '../Spinner';
import { BodyText, HeaderText } from '../Text';
import FileList from './FileList';
import FileUploadForm from './FileUploadForm';
import FileEditForm from './FileEditForm';

import fetchJSON from '../../lib/fetchers/fetchJSON';

const StyledIconButton = styled(IconButton)(ICON_BUTTON_STYLE);

const MESSAGE_BOX_CLASS_PREFIX = 'MessageBox';

const MESSAGE_BOX_CLASSES = {
  error: `${MESSAGE_BOX_CLASS_PREFIX}-error`,
  warning: `${MESSAGE_BOX_CLASS_PREFIX}-warning`,
};

const MessageBox = styled(Box)({
  padding: '.2em .4em',

  [`&.${MESSAGE_BOX_CLASSES.error}`]: {
    backgroundColor: RED,
  },

  [`&.${MESSAGE_BOX_CLASSES.warning}`]: {
    backgroundColor: PURPLE,
  },
});

const Files = (): JSX.Element => {
  const [rawFilesOverview, setRawFilesOverview] = useState<string[][]>([]);
  const [fetchRawFilesError, setFetchRawFilesError] = useState<string>();
  const [isLoadingRawFilesOverview, setIsLoadingRawFilesOverview] =
    useState<boolean>(false);
  const [isEditMode, setIsEditMode] = useState<boolean>(false);

  const fileUploadFormEventEmitter: EventEmitter = new EventEmitter();

  const onAddFileButtonClick = () => {
    fileUploadFormEventEmitter.emit('openFilePicker');
  };

  const onEditFileButtonClick = () => {
    fileUploadFormEventEmitter.emit('clearSelectedFiles');

    setIsEditMode(!isEditMode);
  };

  const fetchRawFilesOverview = async () => {
    setIsLoadingRawFilesOverview(true);

    try {
      const data = await fetchJSON<string[][]>(`${API_BASE_URL}/files`);
      setRawFilesOverview(data);
    } catch (fetchError) {
      setFetchRawFilesError('Failed to get files due to a network issue.');
    }

    setIsLoadingRawFilesOverview(false);
  };

  const buildFileList = (): JSX.Element => {
    let elements: JSX.Element;
    if (isLoadingRawFilesOverview) {
      elements = <Spinner />;
    } else {
      const filesOverview: FileOverviewMetadata[] = rawFilesOverview.map(
        ([fileUUID, fileName, fileSizeInBytes, fileType, fileChecksum]) => ({
          fileChecksum,
          fileName,
          fileSizeInBytes: parseInt(fileSizeInBytes, 10),
          fileType: fileType as FileType,
          fileUUID,
        }),
      );

      elements = isEditMode ? (
        <FileEditForm
          {...{ filesOverview }}
          onEditFilesComplete={fetchRawFilesOverview}
          onPurgeFilesComplete={fetchRawFilesOverview}
        />
      ) : (
        <FileList {...{ filesOverview }} />
      );
    }

    return elements;
  };

  useEffect(() => {
    if (!isEditMode) {
      fetchRawFilesOverview();
    }
  }, [isEditMode]);

  return (
    <Panel>
      <Box
        sx={{
          alignItems: 'center',
          display: 'flex',
          flexDirection: 'row',
          marginBottom: '1em',
          width: '100%',
          '& > :first-child': { flexGrow: 1 },
          '& > :not(:first-child, :last-child)': {
            marginRight: '.3em',
          },
        }}
      >
        <HeaderText text="Files" />
        {!isEditMode && (
          <StyledIconButton onClick={onAddFileButtonClick}>
            <AddIcon />
          </StyledIconButton>
        )}
        <StyledIconButton onClick={onEditFileButtonClick}>
          {isEditMode ? <CheckIcon sx={{ color: BLUE }} /> : <EditIcon />}
        </StyledIconButton>
      </Box>
      {fetchRawFilesError && (
        <MessageBox className={MESSAGE_BOX_CLASSES.error}>
          <BodyText text={fetchRawFilesError} />
        </MessageBox>
      )}
      <FileUploadForm
        {...{ eventEmitter: fileUploadFormEventEmitter }}
        onFileUploadComplete={fetchRawFilesOverview}
      />
      {buildFileList()}
    </Panel>
  );
};

export default Files;
