import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { defineMessages, injectIntl } from 'react-intl';
import { ToastController } from './service';
import { TAB } from '/imports/utils/keyCodes';
import deviceInfo from '/imports/utils/deviceInfo';
import Button from '/imports/ui/components/common/button/component';
import Icon from '/imports/ui/components/common/icon/component';
import update from 'immutability-helper';
import logger from '/imports/startup/client/logger';
import { notify } from '/imports/ui/services/notification';
import { toast } from 'react-toastify';
import _ from 'lodash';
import { registerTitleView, unregisterTitleView } from '/imports/utils/dom-utils';
import Styled from './styles';
import Settings from '/imports/ui/services/settings';
import Checkbox from '/imports/ui/components/common/checkbox/component';

const { isMobile } = deviceInfo;

const propTypes = {
  intl: PropTypes.object.isRequired,
  fileUploadConstraintsHint: PropTypes.bool.isRequired,
  fileSizeMax: PropTypes.number.isRequired,
  filePagesMax: PropTypes.number.isRequired,
  handleSave: PropTypes.func.isRequired,
  dispatchTogglePresentationDownloadable: PropTypes.func.isRequired,
  fileValidMimeTypes: PropTypes.arrayOf(PropTypes.object).isRequired,
  presentations: PropTypes.arrayOf(PropTypes.shape({
    id: PropTypes.string.isRequired,
    filename: PropTypes.string.isRequired,
    isCurrent: PropTypes.bool.isRequired,
    conversion: PropTypes.object,
    upload: PropTypes.object,
  })).isRequired,
  isOpen: PropTypes.bool.isRequired,
};

const defaultProps = {
};

const intlMessages = defineMessages({
  current: {
    id: 'app.presentationUploder.currentBadge',
  },
  title: {
    id: 'app.presentationUploder.title',
    description: 'title of the modal',
  },
  message: {
    id: 'app.presentationUploder.message',
    description: 'message warning the types of files accepted',
  },
  uploadLabel: {
    id: 'app.presentationUploder.uploadLabel',
    description: 'confirm label when presentations are to be uploaded',
  },
  confirmLabel: {
    id: 'app.presentationUploder.confirmLabel',
    description: 'confirm label when no presentations are to be uploaded',
  },
  confirmDesc: {
    id: 'app.presentationUploder.confirmDesc',
    description: 'description of the confirm',
  },
  dismissLabel: {
    id: 'app.presentationUploder.dismissLabel',
    description: 'used in the button that close modal',
  },
  dismissDesc: {
    id: 'app.presentationUploder.dismissDesc',
    description: 'description of the dismiss',
  },
  dropzoneLabel: {
    id: 'app.presentationUploder.dropzoneLabel',
    description: 'message warning where drop files for upload',
  },
  dropzoneImagesLabel: {
    id: 'app.presentationUploder.dropzoneImagesLabel',
    description: 'message warning where drop images for upload',
  },
  browseFilesLabel: {
    id: 'app.presentationUploder.browseFilesLabel',
    description: 'message use on the file browser',
  },
  browseImagesLabel: {
    id: 'app.presentationUploder.browseImagesLabel',
    description: 'message use on the image browser',
  },
  fileToUpload: {
    id: 'app.presentationUploder.fileToUpload',
    description: 'message used in the file selected for upload',
  },
  extraHint: {
    id: 'app.presentationUploder.extraHint',
    description: 'message used to indicate upload file max sizes',
  },
  rejectedError: {
    id: 'app.presentationUploder.rejectedError',
    description: 'some files rejected, please check the file mime types',
  },
  badConnectionError: {
    id: 'app.presentationUploder.connectionClosedError',
    description: 'message indicating that the connection was closed',
  },
  uploadProcess: {
    id: 'app.presentationUploder.upload.progress',
    description: 'message that indicates the percentage of the upload',
  },
  413: {
    id: 'app.presentationUploder.upload.413',
    description: 'error that file exceed the size limit',
  },
  408: {
    id: 'app.presentationUploder.upload.408',
    description: 'error for token request timeout',
  },
  404: {
    id: 'app.presentationUploder.upload.404',
    description: 'error not found',
  },
  401: {
    id: 'app.presentationUploder.upload.401',
    description: 'error for failed upload token request.',
  },
  conversionProcessingSlides: {
    id: 'app.presentationUploder.conversion.conversionProcessingSlides',
    description: 'indicates how many slides were converted',
  },
  genericError: {
    id: 'app.presentationUploder.genericError',
    description: 'generic error while uploading/converting',
  },
  genericConversionStatus: {
    id: 'app.presentationUploder.conversion.genericConversionStatus',
    description: 'indicates that file is being converted',
  },
  TIMEOUT: {
    id: 'app.presentationUploder.conversion.timeout',
  },
  GENERATING_THUMBNAIL: {
    id: 'app.presentationUploder.conversion.generatingThumbnail',
    description: 'indicatess that it is generating thumbnails',
  },
  GENERATING_SVGIMAGES: {
    id: 'app.presentationUploder.conversion.generatingSvg',
    description: 'warns that it is generating svg images',
  },
  GENERATED_SLIDE: {
    id: 'app.presentationUploder.conversion.generatedSlides',
    description: 'warns that were slides generated',
  },
  PAGE_COUNT_EXCEEDED: {
    id: 'app.presentationUploder.conversion.pageCountExceeded',
    description: 'warns the user that the conversion failed because of the page count',
  },
  PDF_HAS_BIG_PAGE: {
    id: 'app.presentationUploder.conversion.pdfHasBigPage',
    description: 'warns the user that the conversion failed because of the pdf page siz that exceeds the allowed limit',
  },
  OFFICE_DOC_CONVERSION_INVALID: {
    id: 'app.presentationUploder.conversion.officeDocConversionInvalid',
    description: '',
  },
  OFFICE_DOC_CONVERSION_FAILED: {
    id: 'app.presentationUploder.conversion.officeDocConversionFailed',
    description: 'warns the user that the conversion failed because of wrong office file',
  },
  UNSUPPORTED_DOCUMENT: {
    id: 'app.presentationUploder.conversion.unsupportedDocument',
    description: 'warns the user that the file extension is not supported',
  },
  isDownloadable: {
    id: 'app.presentationUploder.isDownloadableLabel',
    description: 'presentation is available for downloading by all viewers',
  },
  isNotDownloadable: {
    id: 'app.presentationUploder.isNotDownloadableLabel',
    description: 'presentation is not available for downloading the viewers',
  },
  removePresentation: {
    id: 'app.presentationUploder.removePresentationLabel',
    description: 'select to delete this presentation',
  },
  setAsCurrentPresentation: {
    id: 'app.presentationUploder.setAsCurrentPresentation',
    description: 'set this presentation to be the current one',
  },
  status: {
    id: 'app.presentationUploder.tableHeading.status',
    description: 'aria label status table heading',
  },
  options: {
    id: 'app.presentationUploder.tableHeading.options',
    description: 'aria label for options table heading',
  },
  filename: {
    id: 'app.presentationUploder.tableHeading.filename',
    description: 'aria label for file name table heading',
  },
  uploading: {
    id: 'app.presentationUploder.uploading',
    description: 'uploading label for toast notification',
  },
  uploadStatus: {
    id: 'app.presentationUploder.uploadStatus',
    description: 'upload status for toast notification',
  },
  completed: {
    id: 'app.presentationUploder.completed',
    description: 'uploads complete label for toast notification',
  },
  item: {
    id: 'app.presentationUploder.item',
    description: 'single item label',
  },
  itemPlural: {
    id: 'app.presentationUploder.itemPlural',
    description: 'plural item label',
  },
  clearErrors: {
    id: 'app.presentationUploder.clearErrors',
    description: 'button label for clearing upload errors',
  },
  clearErrorsDesc: {
    id: 'app.presentationUploder.clearErrorsDesc',
    description: 'aria description for button clearing upload error',
  },
  uploadViewTitle: {
    id: 'app.presentationUploder.uploadViewTitle',
    description: 'view name apended to document title',
  }
});

class PresentationUploader extends Component {
  constructor(props) {
    super(props);

    this.state = {
      presentations: [],
      disableActions: false,
      toUploadCount: 0,
    };

    this.toastId = null;
    this.hasError = null;

    // handlers
    this.handleFiledrop = this.handleFiledrop.bind(this);
    this.handleConfirm = this.handleConfirm.bind(this);
    this.handleDismiss = this.handleDismiss.bind(this);
    this.handleRemove = this.handleRemove.bind(this);
    this.handleCurrentChange = this.handleCurrentChange.bind(this);
    // this.handleDismissToast = this.handleDismissToast.bind(this);
    this.handleToggleDownloadable = this.handleToggleDownloadable.bind(this);
    // renders
    this.renderDropzone = this.renderDropzone.bind(this);
    this.renderPicDropzone = this.renderPicDropzone.bind(this);
    this.renderPresentationList = this.renderPresentationList.bind(this);
    this.renderPresentationItem = this.renderPresentationItem.bind(this);
    // this.renderPresentationItemStatus = this.renderPresentationItemStatus.bind(this);
    // this.renderToastList = this.renderToastList.bind(this);
    // this.renderToastItem = this.renderToastItem.bind(this);
    // utilities
    this.deepMergeUpdateFileKey = this.deepMergeUpdateFileKey.bind(this);
    this.updateFileKey = this.updateFileKey.bind(this);
  }

  componentDidUpdate(prevProps) {
    const { isOpen, presentations: propPresentations, intl } = this.props;
    const { presentations } = this.state;

    if (!isOpen && prevProps.isOpen) {
      unregisterTitleView();
    }

    // Updates presentation list when chat modal opens to avoid missing presentations
    if (isOpen && !prevProps.isOpen) {
      registerTitleView(intl.formatMessage(intlMessages.uploadViewTitle));
      const  focusableElements =
        'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])';
      const modal = document.getElementById('upload-modal');
      const firstFocusableElement = modal?.querySelectorAll(focusableElements)[0];
      const focusableContent = modal?.querySelectorAll(focusableElements);
      const lastFocusableElement = focusableContent[focusableContent.length - 1];
      
      firstFocusableElement.focus();
  
      modal.addEventListener('keydown', function(e) {
        let tab = e.key === 'Tab' || e.keyCode === TAB;
        if (!tab) return;
        if (e.shiftKey) {
          if (document.activeElement === firstFocusableElement) {
            lastFocusableElement.focus();
            e.preventDefault();
          }
        } else {
          if (document.activeElement === lastFocusableElement) {
            firstFocusableElement.focus();
            e.preventDefault();
          }
        }
      });

      const presState = Object.values({
        ...propPresentations,
        ...presentations,
      });
      const presStateMapped = presState.map((presentation) => {
        propPresentations.forEach((propPres) => {
          if (propPres.id == presentation.id){
            presentation.isCurrent = propPres.isCurrent;
          }
        })
        return presentation;
      })

      this.setState({
        presentations: presStateMapped,
      })
      
    }

    if (presentations.length > 0) {
      const selected = propPresentations.filter((p) => p.isCurrent);
      if (selected.length > 0) Session.set('selectedToBeNextCurrent', selected[0].id);
    }

    const toastId = Session.get("presentationUploaderToastId");

    // if (toastId) {
    //   if (!prevProps.isOpen && isOpen) {
    //     this.props.handleDismissToast(toastId);
    //   }

    //   toast.update(toastId, {
    //     render: this.props.renderToastList(this.state.presentations, this.state.toUploadCount, intl),
    //   });
    // }
  }

  componentWillUnmount() {
    Session.set('showUploadPresentationView', false);
  }

  // handleDismissToast(toastId) {
  //   return toast.dismiss(toastId);
  // }

  handleFiledrop(files, files2) {
    const { fileValidMimeTypes, intl } = this.props;
    const { toUploadCount } = this.state;
    const validMimes = fileValidMimeTypes.map((fileValid) => fileValid.mime);
    const validExtentions = fileValidMimeTypes.map((fileValid) => fileValid.extension);
    const [accepted, rejected] = _.partition(files
      .concat(files2), (f) => (
        validMimes.includes(f.type) || validExtentions.includes(`.${f.name.split('.').pop()}`)
      ));

    const presentationsToUpload = accepted.map((file) => {
      const id = _.uniqueId(file.name);

      return {
        file,
        isDownloadable: false, // by default new presentations are set not to be downloadable
        isRemovable: true,
        id,
        filename: file.name,
        isCurrent: false,
        conversion: { done: false, error: false },
        upload: { done: false, error: false, progress: 0 },
        onProgress: (event) => {
          if (!event.lengthComputable) {
            this.deepMergeUpdateFileKey(id, 'upload', {
              progress: 100,
              done: true,
            });

            return;
          }

          this.deepMergeUpdateFileKey(id, 'upload', {
            progress: (event.loaded / event.total) * 100,
            done: event.loaded === event.total,
          });
        },
        onConversion: (conversion) => {
          this.deepMergeUpdateFileKey(id, 'conversion', conversion);
        },
        onUpload: (upload) => {
          this.deepMergeUpdateFileKey(id, 'upload', upload);
        },
        onDone: (newId) => {
          this.updateFileKey(id, 'id', newId);
        },
      };
    });

    this.setState(({ presentations }) => ({
      presentations: presentations.concat(presentationsToUpload),
      toUploadCount: (toUploadCount + presentationsToUpload.length),
    }), () => {
      // after the state is set (files have been dropped),
      // make the first of the new presentations current
      if (presentationsToUpload && presentationsToUpload.length) {
        this.handleCurrentChange(presentationsToUpload[0].id);
      }
    });

    if (rejected.length > 0) {
      notify(intl.formatMessage(intlMessages.rejectedError), 'error');
    }
  }

  handleRemove(item, withErr = false) {
    if (withErr) {
      const { presentations } = this.props;
      this.hasError = false;
      return this.setState({
        presentations,
        disableActions: false,
      });
    }

    const { presentations } = this.state;
    const toRemoveIndex = presentations.indexOf(item);
    return this.setState({
      presentations: update(presentations, {
        $splice: [[toRemoveIndex, 1]],
      }),
    }, () => {
      const { presentations: updatedPresentations, oldCurrentId } = this.state;
      const commands = {};

      const currentIndex = updatedPresentations.findIndex((p) => p.isCurrent);
      const actualCurrentIndex = updatedPresentations.findIndex((p) => p.id === oldCurrentId);

      if (currentIndex === -1 && updatedPresentations.length > 0) {
        const newCurrentIndex = actualCurrentIndex === -1 ? 0 : actualCurrentIndex;
        commands[newCurrentIndex] = {
          $apply: (presentation) => {
            const p = presentation;
            p.isCurrent = true;
            return p;
          },
        };
      }

      const updatedCurrent = update(updatedPresentations, commands);
      this.setState({ presentations: updatedCurrent });
    });
  }

  handleCurrentChange(id) {
    const { presentations, disableActions } = this.state;

    if (disableActions) return;

    const currentIndex = presentations.findIndex((p) => p.isCurrent);
    const newCurrentIndex = presentations.findIndex((p) => p.id === id);
    const commands = {};

    // we can end up without a current presentation
    if (currentIndex !== -1) {
      commands[currentIndex] = {
        $apply: (presentation) => {
          const p = presentation;
          p.isCurrent = false;
          return p;
        },
      };
    }

    commands[newCurrentIndex] = {
      $apply: (presentation) => {
        const p = presentation;
        p.isCurrent = true;
        return p;
      },
    };

    const presentationsUpdated = update(presentations, commands);
    this.setState({ presentations: presentationsUpdated });
  }

  deepMergeUpdateFileKey(id, key, value) {
    const applyValue = (toUpdate) => update(toUpdate, { $merge: value });
    this.updateFileKey(id, key, applyValue, '$apply');
  }

  handleConfirm(hasNewUpload) {
    const {
      handleSave,
      selectedToBeNextCurrent,
      presentations: propPresentations,
      dispatchTogglePresentationDownloadable,
    } = this.props;
    const { disableActions, presentations } = this.state;
    const presentationsToSave = presentations;

    this.setState({ disableActions: true });

    presentations.forEach(item => {
      if (item.upload.done) {
        const didDownloadableStateChange = propPresentations.some(
          (p) => p.id === item.id && p.isDownloadable !== item.isDownloadable
        );
        if (didDownloadableStateChange) {
          dispatchTogglePresentationDownloadable(item, item.isDownloadable);
        }
      }
    });

    // if (hasNewUpload) {
    //   this.toastId = toast.info(this.renderToastList(), {
    //     hideProgressBar: true,
    //     autoClose: false,
    //     newestOnTop: true,
    //     closeOnClick: true,
    //     onClose: () => {
    //       this.toastId = null;
    //     },
    //   });
    // }

    if (!disableActions) {
      Session.set('showUploadPresentationView', false);
      return handleSave(presentationsToSave, this.state.toUploadCount, this.props.intl)
        .then(() => {
          const hasError = presentations.some((p) => p.upload.error || p.conversion.error);
          if (!hasError) {
            this.setState({
              disableActions: false,
              toUploadCount: 0,
            });
            return;
          }
          // if there's error we don't want to close the modal
          this.setState({
            disableActions: true,
            // preventClosing: true,
          }, () => {
            // if the selected current has error we revert back to the old one
            const newCurrent = presentations.find((p) => p.isCurrent);
            if (newCurrent.upload.error || newCurrent.conversion.error) {
              this.handleCurrentChange(selectedToBeNextCurrent);
            }
          });
        })
        .catch((error) => {
          logger.error({
            logCode: 'presentationuploader_component_save_error',
            extraInfo: { error },
          }, 'Presentation uploader catch error on confirm');
        });
    }

    Session.set('showUploadPresentationView', false);
    return null;
  }

  handleDismiss() {
    const { presentations } = this.state;
    const { presentations: propPresentations } = this.props;
    const ids = new Set(propPresentations.map((d) => d.ID));
    const merged = [
      ...presentations.filter((d) => !ids.has(d.ID)),
      ...propPresentations,
    ];
    this.setState(
      { presentations: merged },
      Session.set('showUploadPresentationView', false),
    );
  }

  handleToggleDownloadable(item) {
    const { presentations } = this.state;

    const oldDownloadableState = item.isDownloadable;

    const outOfDatePresentationIndex = presentations.findIndex((p) => p.id === item.id);
    const commands = {};
    commands[outOfDatePresentationIndex] = {
      $apply: (presentation) => {
        const p = presentation;
        p.isDownloadable = !oldDownloadableState;
        return p;
      },
    };
    const presentationsUpdated = update(presentations, commands);

    this.setState({
      presentations: presentationsUpdated,
    });
  }

  updateFileKey(id, key, value, operation = '$set') {
    this.setState(({ presentations }) => {
      const fileIndex = presentations.findIndex((f) => f.id === id);

      return fileIndex === -1 ? false : {
        presentations: update(presentations, {
          [fileIndex]: {
            $apply: (file) => update(file, {
              [key]: {
                [operation]: value,
              },
            }),
          },
        }),
      };
    });
  }

  // renderToastItem(item) {
  //   const isUploading = !item.upload.done && item.upload.progress > 0;
  //   const isConverting = !item.conversion.done && item.upload.done;
  //   const hasError = item.conversion.error || item.upload.error;
  //   const isProcessing = (isUploading || isConverting) && !hasError;

  //   let icon = isProcessing ? 'blank' : 'check';
  //   if (hasError) icon = 'circle_close';

  //   return (
  //     <Styled.UploadRow
  //       key={item.id}
  //       onClick={() => {
  //         if (hasError || isProcessing) Session.set('showUploadPresentationView', true);
  //       }}
  //     >
  //       <Styled.FileLine>
  //         <span>
  //           <Icon iconName="file" />
  //         </span>
  //         <Styled.ToastFileName>
  //           <span>{item.filename}</span>
  //         </Styled.ToastFileName>
  //         <Styled.StatusIcon>
  //           <Styled.ToastItemIcon
  //             done={!isProcessing && !hasError}
  //             error={hasError}
  //             loading={isProcessing}
  //             iconName={icon}
  //           />
  //         </Styled.StatusIcon>
  //       </Styled.FileLine>
  //       <Styled.StatusInfo>
  //         <Styled.StatusInfoSpan data-test="presentationStatusInfo" styles={hasError ? 'error' : 'info'}>
  //           {this.renderPresentationItemStatus(item)}
  //         </Styled.StatusInfoSpan>
  //       </Styled.StatusInfo>
  //     </Styled.UploadRow>
  //   );
  // }

  renderExtraHint() {
    const {
      intl,
      fileSizeMax,
      filePagesMax,
    } = this.props;

    const options = {
      0: fileSizeMax/1000000,
      1: filePagesMax,
    };

    return (
      <Styled.ExtraHint>
        {intl.formatMessage(intlMessages.extraHint, options)}
      </Styled.ExtraHint>
    );
  }

  renderPresentationList() {
    const { presentations } = this.state;
    const { intl } = this.props;

    let presentationsSorted = presentations;

    try {
      presentationsSorted = presentations
        .sort((a, b) => a.uploadTimestamp - b.uploadTimestamp)
        .sort((a, b) => a.filename.localeCompare(b.filename))
        .sort((a, b) => b.upload.progress - a.upload.progress)
        .sort((a, b) => b.conversion.done - a.conversion.done)
        .sort((a, b) => {
          const aUploadNotTriggeredYet = !a.upload.done && a.upload.progress === 0;
          const bUploadNotTriggeredYet = !b.upload.done && b.upload.progress === 0;
          return bUploadNotTriggeredYet - aUploadNotTriggeredYet;
        });
    } catch (error) {
      logger.error({
        logCode: 'presentationuploader_component_render_error',
        extraInfo: { error },
      }, 'Presentation uploader catch error on render presentation list');
    }

    return (
      <Styled.FileList>
        <Styled.Table>
          <thead>
            <tr>
              <Styled.VisuallyHidden colSpan={3}>
                {intl.formatMessage(intlMessages.filename)}
              </Styled.VisuallyHidden>
              <Styled.VisuallyHidden>
                {intl.formatMessage(intlMessages.status)}
              </Styled.VisuallyHidden>
              <Styled.VisuallyHidden>
                {intl.formatMessage(intlMessages.options)}
              </Styled.VisuallyHidden>
            </tr>
          </thead>
          <tbody>
            {presentationsSorted.map((item) => this.renderPresentationItem(item))}
          </tbody>
        </Styled.Table>
      </Styled.FileList>
    );
  }

  // renderToastList() {
  //   const { presentations, toUploadCount } = this.state;

  //   if (toUploadCount === 0) {
  //     return this.handleDismissToast(this.toastId);
  //   }

  //   const { intl } = this.props;
  //   let converted = 0;

  //   let presentationsSorted = presentations
  //     .filter((p) => (p.upload.progress || p.conversion.status) && p.file)
  //     .sort((a, b) => a.uploadTimestamp - b.uploadTimestamp)
  //     .sort((a, b) => a.conversion.done - b.conversion.done);

  //   presentationsSorted = presentationsSorted
  //     .splice(0, toUploadCount)
  //     .map((p) => {
  //       if (p.conversion.done) converted += 1;
  //       return p;
  //     });

  //   let toastHeading = '';
  //   const itemLabel = presentationsSorted.length > 1
  //     ? intl.formatMessage(intlMessages.itemPlural)
  //     : intl.formatMessage(intlMessages.item);

  //   if (converted === 0) {
  //     toastHeading = intl.formatMessage(intlMessages.uploading, {
  //       0: presentationsSorted.length,
  //       1: itemLabel,
  //     });
  //   }

  //   if (converted > 0 && converted !== presentationsSorted.length) {
  //     toastHeading = intl.formatMessage(intlMessages.uploadStatus, {
  //       0: converted,
  //       1: presentationsSorted.length,
  //     });
  //   }

  //   if (converted === presentationsSorted.length) {
  //     toastHeading = intl.formatMessage(intlMessages.completed, {
  //       0: converted,
  //     });
  //   }

  //   return (
  //     <Styled.ToastWrapper>
  //       <Styled.UploadToastHeader>
  //         <Styled.UploadIcon iconName="upload" />
  //         <Styled.UploadToastTitle>{toastHeading}</Styled.UploadToastTitle>
  //       </Styled.UploadToastHeader>
  //       <Styled.InnerToast>
  //         <div>
  //           <div>
  //             {presentationsSorted.map((item) => this.renderToastItem(item))}
  //           </div>
  //         </div>
  //       </Styled.InnerToast>
  //     </Styled.ToastWrapper>
  //   );
  // }

  renderPresentationItem(item) {
    const { disableActions } = this.state;
    const {
      intl,
      selectedToBeNextCurrent,
      allowDownloadable
    } = this.props;

    const isActualCurrent = selectedToBeNextCurrent ? item.id === selectedToBeNextCurrent : item.isCurrent;
    const isUploading = !item.upload.done && item.upload.progress > 0;
    const isConverting = !item.conversion.done && item.upload.done;
    const hasError = item.conversion.error || item.upload.error;
    const isProcessing = (isUploading || isConverting) && !hasError;

    if (hasError) {
      this.hasError = true;
    }

    const formattedDownloadableLabel = !item.isDownloadable
      ? intl.formatMessage(intlMessages.isDownloadable)
      : intl.formatMessage(intlMessages.isNotDownloadable);

    const formattedDownloadableAriaLabel = `${formattedDownloadableLabel} ${item.filename}`;

    const { animations } = Settings.application;

    const { isRemovable } = item; 

    return (
      <Styled.PresentationItem
        key={item.id}
        isNew={item.id.indexOf(item.filename) !== -1}
        uploading={isUploading}
        converting={isConverting}
        error={hasError}
        animated={isProcessing}
        animations={animations}
      >
        <Styled.TableItemIcon>
          <Icon iconName="file" />
        </Styled.TableItemIcon>
        {
          isActualCurrent
            ? (
              <Styled.TableItemCurrent>
                <Styled.CurrentLabel>
                  {intl.formatMessage(intlMessages.current)}
                </Styled.CurrentLabel>
              </Styled.TableItemCurrent>
            )
            : null
        }
        <Styled.TableItemName colSpan={!isActualCurrent ? 2 : 0}>
          <span>{item.filename}</span>
        </Styled.TableItemName>
        <Styled.TableItemStatus colSpan={hasError ? 2 : 0}>
          {this.props.renderPresentationItemStatus(item, intl)}
        </Styled.TableItemStatus>
        {hasError ? null : (
          <Styled.TableItemActions notDownloadable={!allowDownloadable}>
            {allowDownloadable ? (
              <Styled.DownloadButton
                disabled={disableActions}
                isDownloadable={item.isDownloadable}
                label={formattedDownloadableLabel}
                data-test={item.isDownloadable ? 'disallowPresentationDownload' : 'allowPresentationDownload'}
                aria-label={formattedDownloadableAriaLabel}
                hideLabel
                size="sm"
                icon={item.isDownloadable ? 'download' : 'download-off'}
                onClick={() => this.handleToggleDownloadable(item)}
                animations={animations}
              />
              ) : null
            }
            <Styled.ItemAction>
              <Checkbox
              animations={animations}
              ariaLabel={`${intl.formatMessage(intlMessages.setAsCurrentPresentation)} ${item.filename}`}
              checked={item.isCurrent}
              keyValue={item.id}
              onChange={() => this.handleCurrentChange(item.id)}
              disabled={disableActions}
              />
            </Styled.ItemAction>
            {isRemovable ? (
              <Styled.RemoveButton
                disabled={disableActions}
                label={intl.formatMessage(intlMessages.removePresentation)}
                data-test="removePresentation"
                aria-label={`${intl.formatMessage(intlMessages.removePresentation)} ${item.filename}`}
                size="sm"
                icon="delete"
                hideLabel
                onClick={() => this.handleRemove(item)}
                animations={animations}
              />
              ) : null
            }
          </Styled.TableItemActions>
        )}
      </Styled.PresentationItem>
    );
  }

  renderDropzone() {
    const {
      intl,
      fileValidMimeTypes,
    } = this.props;

    const { disableActions } = this.state;

    if (disableActions && !this.hasError) return null;

    return this.hasError ? (
      <div>
        <Button
          color="danger"
          onClick={() => this.handleRemove(null, true)}
          label={intl.formatMessage(intlMessages.clearErrors)}
          aria-describedby="clearErrorDesc"
        />
        <div id="clearErrorDesc" style={{ display: 'none' }}>
          {intl.formatMessage(intlMessages.clearErrorsDesc)}
        </div>
      </div>
    ) : (
      // Until the Dropzone package has fixed the mime type hover validation, the rejectClassName
      // prop is being remove to prevent the error styles from being applied to valid file types.
      // Error handling is being done in the onDrop prop.
      <Styled.UploaderDropzone
        multiple
        activeClassName={"dropzoneActive"}
        accept={fileValidMimeTypes.map((fileValid) => fileValid.extension)}
        disablepreview="true"
        onDrop={this.handleFiledrop}
      >
        <Styled.DropzoneIcon iconName="upload" />
        <Styled.DropzoneMessage>
          {intl.formatMessage(intlMessages.dropzoneLabel)}
          &nbsp;
          <Styled.DropzoneLink>
            {intl.formatMessage(intlMessages.browseFilesLabel)}
          </Styled.DropzoneLink>
        </Styled.DropzoneMessage>
      </Styled.UploaderDropzone>
    );
  }

  renderPicDropzone() {
    const {
      intl,
    } = this.props;

    const { disableActions } = this.state;

    if (disableActions && !this.hasError) return null;

    return this.hasError ? (
      <div>
        <Button
          color="danger"
          onClick={() => this.handleRemove(null, true)}
          label={intl.formatMessage(intlMessages.clearErrors)}
          aria-describedby="clearErrorDesc"
        />
        <div id="clearErrorDesc" style={{ display: 'none' }}>
          {intl.formatMessage(intlMessages.clearErrorsDesc)}
        </div>
      </div>
    ) : (
      <Styled.UploaderDropzone
        multiple
        accept="image/*"
        disablepreview="true"
        data-test="fileUploadDropZone"
        onDrop={this.handleFiledrop}
      >
        <Styled.DropzoneIcon iconName="upload" />
        <Styled.DropzoneMessage>
          {intl.formatMessage(intlMessages.dropzoneImagesLabel)}
          &nbsp;
          <Styled.DropzoneLink>
            {intl.formatMessage(intlMessages.browseImagesLabel)}
          </Styled.DropzoneLink>
        </Styled.DropzoneMessage>
      </Styled.UploaderDropzone>
    );
  }

  // renderPresentationItemStatus(item) {
  //   const { intl } = this.props;
  //   if (!item.upload.done && item.upload.progress === 0) {
  //     return intl.formatMessage(intlMessages.fileToUpload);
  //   }

  //   if (!item.upload.done && !item.upload.error) {
  //     return intl.formatMessage(intlMessages.uploadProcess, {
  //       0: Math.floor(item.upload.progress).toString(),
  //     });
  //   }

  //   const constraint = {};

  //   if (item.upload.done && item.upload.error) {
  //     if (item.conversion.status === 'FILE_TOO_LARGE') {
  //       constraint['0'] = ((item.conversion.maxFileSize) / 1000 / 1000).toFixed(2);
  //     }

  //     if (item.upload.progress < 100) {
  //       const errorMessage = intlMessages.badConnectionError;
  //       return intl.formatMessage(errorMessage);
  //     }

  //     const errorMessage = intlMessages[item.upload.status] || intlMessages.genericError;
  //     return intl.formatMessage(errorMessage, constraint);
  //   }

  //   if (!item.conversion.done && item.conversion.error) {
  //     const errorMessage = intlMessages[item.conversion.status] || intlMessages.genericConversionStatus;

  //     switch (item.conversion.status) {
  //       case 'PAGE_COUNT_EXCEEDED':
  //         constraint['0'] = item.conversion.maxNumberPages;
  //         break;
  //       case 'PDF_HAS_BIG_PAGE':
  //         constraint['0'] = (item.conversion.bigPageSize / 1000 / 1000).toFixed(2);
  //         break;
  //       default:
  //         break;
  //     }

  //     return intl.formatMessage(errorMessage, constraint);
  //   }

  //   if (!item.conversion.done && !item.conversion.error) {
  //     if (item.conversion.pagesCompleted < item.conversion.numPages) {
  //       return intl.formatMessage(intlMessages.conversionProcessingSlides, {
  //         0: item.conversion.pagesCompleted,
  //         1: item.conversion.numPages,
  //       });
  //     }

  //     const conversionStatusMessage = intlMessages[item.conversion.status]
  //       || intlMessages.genericConversionStatus;
  //     return intl.formatMessage(conversionStatusMessage);
  //   }

  //   return null;
  // }

  render() {
    const {
      isOpen,
      isPresenter,
      intl,
      fileUploadConstraintsHint,
    } = this.props;
    if (!isPresenter) return null;
    const { presentations, disableActions } = this.state;

    let hasNewUpload = false;

    presentations.forEach((item) => {
      if (item.id.indexOf(item.filename) !== -1 && item.upload.progress === 0) hasNewUpload = true;
    });

    return (<>
      <ToastController intl = {intl} />
      {isOpen ? (
        <Styled.UploaderModal id="upload-modal">
          <Styled.ModalInner>
            <Styled.ModalHeader>
              <h1>{intl.formatMessage(intlMessages.title)}</h1>
              <Styled.ActionWrapper>
                <Styled.DismissButton
                  color="secondary"
                  onClick={this.handleDismiss}
                  label={intl.formatMessage(intlMessages.dismissLabel)}
                  aria-describedby={intl.formatMessage(intlMessages.dismissDesc)}
                />
                <Styled.ConfirmButton
                  data-test="confirmManagePresentation"
                  color="primary"
                  onClick={() => this.handleConfirm(hasNewUpload)}
                  disabled={disableActions}
                  label={hasNewUpload
                    ? intl.formatMessage(intlMessages.uploadLabel)
                    : intl.formatMessage(intlMessages.confirmLabel)}
                />
              </Styled.ActionWrapper>
            </Styled.ModalHeader>

            <Styled.ModalHint>
              {`${intl.formatMessage(intlMessages.message)}`}
              {fileUploadConstraintsHint ? this.renderExtraHint() : null}
            </Styled.ModalHint>
            {this.renderPresentationList()}
            {isMobile ? this.renderPicDropzone() : null}
            {this.renderDropzone()}
          </Styled.ModalInner>
        </Styled.UploaderModal>
      ) : null
    }</>)
  }
}

PresentationUploader.propTypes = propTypes;
PresentationUploader.defaultProps = defaultProps;

export default injectIntl(PresentationUploader);
