import _extends from "@babel/runtime/helpers/extends";
import React, { useCallback, useEffect, useState, useRef } from 'react';
import Loadable from 'react-loadable';
import { isExternalImageIdentifier, isFileIdentifier, toCommonMediaClientError } from '@atlaskit/media-client';
import { Text } from '@atlaskit/primitives/compiled';
import { FormattedMessage } from 'react-intl-next';
import { messages } from '@atlaskit/media-ui';
import { isCodeViewerItem } from '@atlaskit/media-ui/codeViewer';
import { useFileState, useMediaClient } from '@atlaskit/media-client-react';
import { Outcome } from './domain';
import { Spinner } from './loading';
import ErrorMessage from './errorMessage';
import { MediaViewerError } from './errors';
import { ErrorViewDownloadButton } from './download';
import { withAnalyticsEvents } from '@atlaskit/analytics-next';
import { createCommencedEvent } from './analytics/events/operational/commenced';
import { createLoadSucceededEvent } from './analytics/events/operational/loadSucceeded';
import { fireAnalytics, getFileAttributes } from './analytics';
import { InteractiveImg } from './viewers/image/interactive-img';
import ArchiveViewerLoader from './viewers/archiveSidebar/archiveViewerLoader';
import { startMediaFileUfoExperience, succeedMediaFileUfoExperience } from './analytics/ufoExperiences';
import { CustomViewer } from './viewers/customViewer/customViewer';
import { fg } from '@atlaskit/platform-feature-flags';
const ImageViewer = Loadable({
  loader: () => import( /* webpackChunkName: "@atlaskit-internal_imageViewer" */'./viewers/image').then(mod => mod.ImageViewer),
  loading: () => /*#__PURE__*/React.createElement(Spinner, null)
});
const VideoViewer = Loadable({
  loader: () => import( /* webpackChunkName: "@atlaskit-internal_videoViewer" */'./viewers/video').then(mod => mod.VideoViewer),
  loading: () => /*#__PURE__*/React.createElement(Spinner, null)
});
const AudioViewer = Loadable({
  loader: () => import( /* webpackChunkName: "@atlaskit-internal_audioViewer" */'./viewers/audio').then(mod => mod.AudioViewer),
  loading: () => /*#__PURE__*/React.createElement(Spinner, null)
});
const DocViewer = Loadable({
  loader: () => import( /* webpackChunkName: "@atlaskit-internal_docViewer" */'./viewers/doc').then(mod => mod.DocViewer),
  loading: () => /*#__PURE__*/React.createElement(Spinner, null)
});
const DocNextViewer = Loadable({
  loader: () => import( /* webpackChunkName: "@atlaskit-internal_docNextViewer" */'./viewers/doc-next').then(mod => mod.DocViewer),
  loading: () => /*#__PURE__*/React.createElement(Spinner, null)
});
const CodeViewer = Loadable({
  loader: () => import( /* webpackChunkName: "@atlaskit-internal_codeViewer" */'./viewers/codeViewer').then(mod => mod.CodeViewer),
  loading: () => /*#__PURE__*/React.createElement(Spinner, null)
});
const SvgViewer = Loadable({
  loader: () =>
  // @ts-ignore: [PIT-1685] Fails in post-office due to backwards incompatibility issue with React 18
  import( /* webpackChunkName: "@atlaskit-internal_svgViewer" */'./viewers/svg').then(mod => mod.SvgViewer),
  loading: () => /*#__PURE__*/React.createElement(Spinner, null)
});
// Consts
export const isExternalImageItem = fileItem => fileItem === 'external-image';
export const isFileStateItem = fileItem => !isExternalImageItem(fileItem);
export const MAX_FILE_SIZE_SUPPORTED_BY_CODEVIEWER = 10 * 1024 * 1024;
export const ItemViewerBase = ({
  identifier,
  showControls,
  onClose,
  previewCount,
  contextId,
  createAnalyticsEvent,
  viewerOptions,
  traceContext
}) => {
  // States and Refs
  const [item, setItem] = useState(Outcome.pending());
  const fileStateFlagsRef = useRef({
    wasStatusUploading: false,
    wasStatusProcessing: false
  });
  const createAnalyticsEventRef = useRef(createAnalyticsEvent);
  createAnalyticsEventRef.current = createAnalyticsEvent;

  // Hooks
  const mediaClient = useMediaClient();
  const {
    fileState
  } = useFileState(isExternalImageIdentifier(identifier) ? '' : identifier.id, {
    collectionName: isExternalImageIdentifier(identifier) ? '' : identifier.collectionName,
    skipRemote: isExternalImageIdentifier(identifier)
  });
  const renderDownloadButton = useCallback((fileState, error) => {
    const collectionName = isFileIdentifier(identifier) ? identifier.collectionName : undefined;
    return /*#__PURE__*/React.createElement(ErrorViewDownloadButton, {
      fileState: fileState,
      mediaClient: mediaClient,
      error: error,
      collectionName: collectionName,
      traceContext: traceContext
    });
  }, [mediaClient, identifier, traceContext]);

  // Did mount

  useEffect(() => {
    if (isExternalImageIdentifier(identifier)) {
      return;
    }
    fireAnalytics(createCommencedEvent(identifier === null || identifier === void 0 ? void 0 : identifier.id, traceContext), createAnalyticsEventRef.current);
    startMediaFileUfoExperience();
  }, [identifier, traceContext]);
  useEffect(() => {
    if (isExternalImageIdentifier(identifier)) {
      // external images do not need to talk to our backend,
      // so therefore no need for media-client subscriptions.
      // just set a successful outcome of type "external-image".
      setItem(Outcome.successful('external-image'));
      return;
    }

    // File Subscription
    if (fileState) {
      const {
        status
      } = fileState;
      if (fileState.status !== 'error') {
        // updateFileStateFlag

        if (status === 'processing') {
          fileStateFlagsRef.current.wasStatusProcessing = true;
        } else if (status === 'uploading') {
          fileStateFlagsRef.current.wasStatusUploading = true;
        }
        setItem(Outcome.successful(fileState));
      } else {
        setItem(Outcome.failed(new MediaViewerError('itemviewer-fetch-metadata', toCommonMediaClientError(fileState))));
      }
    }
  }, [fileState, identifier]);
  const onSuccess = useCallback(() => {
    item.whenSuccessful(fileItem => {
      if (isFileStateItem(fileItem)) {
        const fileAttributes = getFileAttributes(fileItem);
        fireAnalytics(createLoadSucceededEvent(fileAttributes, traceContext), createAnalyticsEventRef.current);
        succeedMediaFileUfoExperience({
          fileAttributes,
          fileStateFlags: fileStateFlagsRef.current
        });
      }
    });
  }, [item, traceContext]);
  const onLoadFail = useCallback(mediaViewerError => {
    setItem(Outcome.failed(mediaViewerError, fileState));
  }, [fileState]);
  const renderItem = fileItem => {
    var _viewerOptions$custom;
    const collectionName = isFileIdentifier(identifier) ? identifier.collectionName : undefined;
    const viewerProps = {
      mediaClient,
      item: fileItem,
      collectionName,
      onClose,
      previewCount,
      viewerOptions,
      traceContext
    };
    const customRenderer = viewerOptions === null || viewerOptions === void 0 ? void 0 : (_viewerOptions$custom = viewerOptions.customRenderers) === null || _viewerOptions$custom === void 0 ? void 0 : _viewerOptions$custom.find(renderer => renderer.shouldUseCustomRenderer({
      fileItem
    }));
    if (customRenderer) {
      return /*#__PURE__*/React.createElement(CustomViewer, _extends({
        customRendererConfig: customRenderer,
        onError: onLoadFail,
        onSuccess: onSuccess
      }, viewerProps));
    }

    // TODO: fix all of the item errors

    if (isCodeViewerItem(fileItem.name, fileItem.mimeType)) {
      //Render error message if code file has size over 10MB.
      //Required by https://product-fabric.atlassian.net/browse/MEX-1788
      if (fileItem.size > MAX_FILE_SIZE_SUPPORTED_BY_CODEVIEWER) {
        return renderError(new MediaViewerError('codeviewer-file-size-exceeds'), fileItem);
      }
      return /*#__PURE__*/React.createElement(CodeViewer, _extends({
        onSuccess: onSuccess,
        onError: onLoadFail
      }, viewerProps));
    }
    if (isFileIdentifier(identifier) && fileItem.mimeType === 'image/svg+xml') {
      return /*#__PURE__*/React.createElement(SvgViewer, {
        identifier: identifier,
        onLoad: onSuccess,
        onError: onLoadFail,
        onClose: onClose,
        traceContext: traceContext
      });
    }
    const {
      mediaType
    } = fileItem;
    switch (mediaType) {
      case 'image':
        return /*#__PURE__*/React.createElement(ImageViewer, _extends({
          onLoad: onSuccess,
          onError: onLoadFail,
          contextId: contextId
        }, viewerProps));
      case 'audio':
        return /*#__PURE__*/React.createElement(AudioViewer, _extends({
          showControls: showControls,
          onCanPlay: onSuccess,
          onError: onLoadFail
        }, viewerProps));
      case 'video':
        return /*#__PURE__*/React.createElement(VideoViewer, _extends({
          identifier: identifier,
          showControls: showControls,
          onCanPlay: onSuccess,
          onError: onLoadFail
        }, viewerProps));
      case 'doc':
        if (fg('media_document_viewer')) {
          return /*#__PURE__*/React.createElement(DocNextViewer, _extends({
            onSuccess: onSuccess,
            onError: onLoadFail
          }, viewerProps));
        }
        return /*#__PURE__*/React.createElement(DocViewer, _extends({
          onSuccess: onSuccess,
          onError: onLoadFail
        }, viewerProps));
      case 'archive':
        return /*#__PURE__*/React.createElement(ArchiveViewerLoader, _extends({
          onSuccess: onSuccess,
          onError: onLoadFail
        }, viewerProps));
    }
    return renderError(new MediaViewerError('unsupported'), fileItem);
  };
  const renderError = useCallback((error, fileItem) => {
    if (fileItem) {
      let fileState;
      if (fileItem === 'external-image') {
        // external image error outcome
        fileState = {
          id: 'external-image',
          status: 'error'
        };
      } else {
        // FileState error outcome
        fileState = fileItem;
      }
      return /*#__PURE__*/React.createElement(ErrorMessage, {
        fileId: isFileIdentifier(identifier) ? identifier.id : 'undefined',
        error: error,
        fileState: fileState,
        fileStateFlags: fileStateFlagsRef.current,
        traceContext: traceContext
      }, /*#__PURE__*/React.createElement(Text, null, /*#__PURE__*/React.createElement(FormattedMessage, messages.try_downloading_file)), renderDownloadButton(fileState, error));
    } else {
      return /*#__PURE__*/React.createElement(ErrorMessage, {
        fileId: isFileIdentifier(identifier) ? identifier.id : 'undefined',
        error: error,
        fileStateFlags: fileStateFlagsRef.current
      });
    }
  }, [identifier, renderDownloadButton, traceContext]);
  return item.match({
    successful: fileItem => {
      if (fileItem === 'external-image') {
        // render an external image
        const {
          dataURI,
          name
        } = identifier;
        return /*#__PURE__*/React.createElement(InteractiveImg, {
          src: dataURI,
          alt: name !== null && name !== void 0 ? name : '',
          onLoad: () => {
            fireAnalytics(createLoadSucceededEvent({
              fileId: 'external-image'
            }), createAnalyticsEventRef.current);
            succeedMediaFileUfoExperience({
              fileAttributes: {
                fileId: 'external-image'
              },
              fileStateFlags: fileStateFlagsRef.current
            });
          },
          onError: () => {
            setItem(Outcome.failed(new MediaViewerError('imageviewer-external-onerror')));
          }
        });
      } else {
        // render a FileState fetched through media-client
        switch (fileItem.status) {
          case 'processed':
          case 'uploading':
          case 'processing':
            return renderItem(fileItem);
          case 'failed-processing':
            if (fileItem.mediaType === 'doc' && fileItem.mimeType === 'application/pdf') {
              return renderItem(fileItem);
            }
            return renderError(new MediaViewerError('itemviewer-file-failed-processing-status'), fileItem);
          case 'error':
            return renderError(new MediaViewerError('itemviewer-file-error-status', toCommonMediaClientError(fileItem)), fileItem);
        }
      }
    },
    pending: () => /*#__PURE__*/React.createElement(Spinner, null),
    failed: error => renderError(error, item.data)
  });
};
const ViewerWithKey = props => {
  const {
    identifier
  } = props;
  const key = isFileIdentifier(identifier) ? identifier.id : identifier.dataURI;
  return /*#__PURE__*/React.createElement(ItemViewerBase, _extends({}, props, {
    key: key
  }));
};
export const ItemViewer = withAnalyticsEvents()(ViewerWithKey);