// @flow
import React, { useState } from 'react';
import FileSelector from 'component/common/file-selector';
import Button from 'component/button';
import FileThumbnail from 'component/fileThumbnail';
import * as MODALS from 'constants/modal_types';
import { serializeFileObj } from 'util/file';
import { tusIsSessionLocked } from 'util/tus';

type Props = {
  uploadItem: FileUploadItem,
  doPublishResume: (any) => void,
  doUpdateUploadRemove: (string, any) => void,
  doOpenModal: (string, {}) => void,
};

export default function WebUploadItem(props: Props) {
  const { uploadItem, doPublishResume, doUpdateUploadRemove, doOpenModal } = props;
  const { params, file, fileFingerprint, progress, status, resumable, uploader } = uploadItem;

  const [showFileSelector, setShowFileSelector] = useState(false);
  const locked = tusIsSessionLocked(params.guid);

  function handleFileChange(newFile: WebFile, clearName = true) {
    if (serializeFileObj(newFile) === fileFingerprint) {
      setShowFileSelector(false);
      doPublishResume({ ...params, file_path: newFile });
      if (!params.guid) {
        // Can remove this if-block after January 2022.
        doUpdateUploadRemove('', params);
      }
    } else {
      doOpenModal(MODALS.CONFIRM, {
        title: __('Invalid file'),
        subtitle: __('It appears to be a different or modified file.'),
        body: <p className="help--warning">{__('Please select the same file from the initial upload.')}</p>,
        onConfirm: (closeModal) => closeModal(),
        hideCancel: true,
      });
    }
  }

  function handleCancel() {
    doOpenModal(MODALS.CONFIRM, {
      title: __('Cancel upload'),
      subtitle: __('Cancel and remove the selected upload?'),
      body: params.name ? <p className="empty">{`lbry://${params.name}`}</p> : undefined,
      onConfirm: (closeModal) => {
        if (tusIsSessionLocked(params.guid)) {
          // Corner-case: it's possible for the upload to resume in another tab
          // after the modal has appeared. Make a final lock-check here.
          // We can invoke a toast here, but just do nothing for now.
          // The upload status should make things obvious.
        } else {
          if (uploader) {
            if (resumable) {
              // $FlowFixMe - couldn't resolve to TusUploader manually.
              uploader.abort(true); // TUS
            } else {
              uploader.abort(); // XHR
            }
          }

          // The second parameter (params) can be removed after January 2022.
          doUpdateUploadRemove(params.guid, params);
        }
        closeModal();
      },
    });
  }

  function resolveProgressStr() {
    if (locked) {
      return __('File being uploaded in another tab or window.');
    }

    if (!uploader) {
      if (status === 'notify') {
        return __('File uploaded to server.');
      } else {
        return __('Stopped.');
      }
    }

    if (resumable) {
      if (status) {
        switch (status) {
          case 'retry':
            return __('Uploading...');
          case 'error':
            return __('Failed.');
          case 'conflict':
            return __('Stopped. Duplicate session detected.');
          case 'notify':
            return __('Processing file. Please wait...');
          default:
            return status;
        }
      } else {
        const progressInt = parseInt(progress);
        return progressInt === 100 ? __('Processing...') : `${__('Uploading...')} (${progressInt}%)`;
      }
    } else {
      return __('Uploading...');
    }
  }

  function getRetryButton() {
    if (!resumable || locked) {
      return null;
    }

    if (uploader) {
      // Should still be uploading. Don't show.
      return null;
    } else {
      // Refreshed or connection broken ...

      if (status === 'notify') {
        // ... but 'notify' sent, so we have to assume it is processed.
        // Can't do much until the polling API is available.
        return null;
      }

      const isFileActive = file instanceof File;
      return (
        <Button
          label={isFileActive ? __('Resume') : __('Retry')}
          button="link"
          onClick={() => {
            if (isFileActive) {
              doPublishResume({ ...params, file_path: file });
            } else {
              setShowFileSelector(true);
            }
          }}
          disabled={showFileSelector}
        />
      );
    }
  }

  function getCancelButton() {
    if (!locked) {
      if (status === 'notify') {
        return (
          <Button
            button="link"
            label={__('Remove')}
            onClick={() => {
              doOpenModal(MODALS.CONFIRM, {
                title: __('Remove entry?'),
                body: (
                  <>
                    <p>
                      {__('The file was successfully uploaded, but we could not retrieve the confirmation status.')}
                    </p>
                    <p>
                      {__(
                        'Wait 5-10 minutes, then refresh and check the Uploads list and Wallet transactions before attempting to re-upload.'
                      )}
                    </p>
                    <p className="section__subtitle">
                      {__('This entry can be safely removed if the transaction is visible in those pages.')}
                    </p>
                    <div className="help--warning">
                      <p>{__('Press OK to clear this entry from the "Currently Uploading" list.')}</p>
                    </div>
                  </>
                ),
                onConfirm: (closeModal) => {
                  doUpdateUploadRemove(params.guid);
                  closeModal();
                },
              });
            }}
          />
        );
      }

      return <Button label={__('Cancel')} button="link" onClick={handleCancel} />;
    }
  }

  function getFileSelector() {
    return (
      <div className="claim-preview--padded">
        <FileSelector
          label={__('File')}
          onFileChosen={handleFileChange}
          // https://stackoverflow.com/questions/19107685/safari-input-type-file-accept-video-ignores-mp4-files
          accept={'video/mp4,video/x-m4v,video/*,audio/*'}
          placeholder={__('Select the file to resume upload...')}
        />
      </div>
    );
  }

  function getProgressBar() {
    return (
      <>
        <div className="claim-upload__progress--label">lbry://{params.name}</div>
        <div className={'claim-upload__progress--outer card--inline'}>
          <div className={'claim-upload__progress--inner'} style={{ width: `${progress}%` }}>
            <span className="claim-upload__progress--inner-text">{resolveProgressStr()}</span>
          </div>
        </div>
      </>
    );
  }

  React.useEffect(() => {
    if (locked && showFileSelector) {
      setShowFileSelector(false);
    }
  }, [locked, showFileSelector]);

  return (
    <li className={'web-upload-item claim-preview claim-preview--inactive card--inline'}>
      <FileThumbnail thumbnail={params.thumbnail_url} />
      <div className={'claim-preview-metadata'}>
        <div className="claim-preview-info">
          <div className="claim-preview__title">{params.title}</div>
          <div className="card__actions--inline">
            {getRetryButton()}
            {getCancelButton()}
          </div>
        </div>
        {showFileSelector && getFileSelector()}
        {!showFileSelector && getProgressBar()}
      </div>
    </li>
  );
}
