"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;
var _react = _interopRequireWildcard(require("react"));
var _styledModalComponents = require("../styledModalComponents");
var _icons = require("../../../assets/icons");
var _ModalHeaderComponent = _interopRequireDefault(require("../ModalHeaderComponent"));
var _reactRedux = require("react-redux");
var _Button = _interopRequireDefault(require("../../styled/Button"));
var _MediaComponents = require("../../styled/StyledInputComponents/MediaComponents");
var _chatSettingsSlice = require("../../../roomStore/chatSettingsSlice");
var _reactNative = require("react-native");
var _expoVideo = require("expo-video");
var FileSystem = _interopRequireWildcard(require("expo-file-system/legacy"));
var MediaLibrary = _interopRequireWildcard(require("expo-media-library"));
var _ToastContext = require("../../../context/ToastContext");
var _PdfView = _interopRequireDefault(require("./PdfView"));
var _DocumentViewer = _interopRequireDefault(require("./DocumentViewer"));
var _AudioMessage = _interopRequireDefault(require("../../styled/AudioMessage"));
var _mimeToExtension = require("../../../helpers/mimeToExtension");
var _jsxRuntime = require("react/jsx-runtime");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
// MIME types Google's gview embed renders reliably. Everything else
// falls through to the info-card so the user can still download.
const GVIEW_PREVIEWABLE = new Set(['application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/vnd.ms-powerpoint', 'application/vnd.openxmlformats-officedocument.presentationml.presentation', 'text/plain', 'text/csv', 'application/rtf']);
const isGviewPreviewable = mime => {
  if (!mime) {
    return false;
  }
  return GVIEW_PREVIEWABLE.has(mime.toLowerCase().split(';')[0].trim());
};

// Full-screen video preview on expo-video (expo-av <Video> is deprecated
// and rendered blank on Android). `contentFit: contain` fits the clip to
// the area with the surrounding letterbox painted as the view's own
// (transparent → theme) background, NOT black. `textureView` so the play
// overlay composites on top and nothing is clipped on Android.
const ModalVideo = ({
  uri
}) => {
  const [showPlay, setShowPlay] = (0, _react.useState)(true);
  const player = (0, _expoVideo.useVideoPlayer)(uri, p => {
    p.muted = false;
  });
  (0, _react.useEffect)(() => {
    const sub = player.addListener('playingChange', ({
      isPlaying
    }) => {
      if (isPlaying) {
        setShowPlay(false);
      }
    });
    return () => sub.remove();
  }, [player]);
  const handlePlay = () => {
    setShowPlay(false);
    player.play();
  };
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
    style: {
      flex: 1,
      width: '100%'
    },
    children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_expoVideo.VideoView, {
      player: player,
      style: {
        flex: 1,
        backgroundColor: 'transparent'
      },
      contentFit: "contain",
      nativeControls: true,
      surfaceType: "textureView",
      allowsFullscreen: true
    }), showPlay && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
      activeOpacity: 0.8,
      onPress: handlePlay,
      style: _reactNative.StyleSheet.absoluteFillObject,
      children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
        style: styles.playOverlay,
        children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
          style: styles.playButton,
          children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_icons.PlayIcon, {
            width: 28,
            height: 28
          })
        })
      })
    })]
  });
};
const FilePreviewModal = ({
  handleCloseModal
}) => {
  const dispatch = (0, _reactRedux.useDispatch)();
  const {
    showToast
  } = (0, _ToastContext.useToast)();

  // Cache the SAF directory the user granted so saving several documents
  // in a row doesn't re-prompt for a folder every time (Android only).
  const safDirUriRef = (0, _react.useRef)(null);
  const {
    activeFile
  } = (0, _reactRedux.useSelector)(state => state.chatSettingStore);
  if (!activeFile) {
    return null;
  }
  const requestStoragePermission = async () => {
    try {
      const {
        status
      } = await MediaLibrary.requestPermissionsAsync();
      return status === 'granted';
    } catch (error) {
      console.error('Error requesting permission:', error);
      return false;
    }
  };
  const saveToGallery = async () => {
    const hasPermission = await requestStoragePermission();
    if (!hasPermission) {
      _reactNative.Alert.alert('Permission Denied', 'Storage permission is required to save files to the gallery.');
      return;
    }
    try {
      const fileName = (0, _mimeToExtension.ensureFilenameHasExtension)(activeFile.fileName, activeFile.mimetype);
      const filePath = FileSystem.cacheDirectory + fileName;
      const download = await FileSystem.downloadAsync(activeFile.fileURL, filePath);
      if (download.status === 200) {
        await MediaLibrary.saveToLibraryAsync(download.uri);
        showToast({
          id: Date.now().toString(),
          title: 'Success',
          message: 'Save successful',
          type: 'success'
        });
      } else {
        _reactNative.Alert.alert('Error', 'Failed to save the file.');
      }
    } catch (err) {
      _reactNative.Alert.alert('Error', `Failed to save the file: ${activeFile.fileName}`);
    }
  };
  const saveFileToDownloads = async () => {
    try {
      const fileName = (0, _mimeToExtension.ensureFilenameHasExtension)(activeFile.fileName, activeFile.mimetype);
      const filePath = FileSystem.cacheDirectory + fileName;
      const download = await FileSystem.downloadAsync(activeFile.fileURL, filePath);
      if (download.status !== 200) {
        _reactNative.Alert.alert('Error', 'Failed to save the file.');
        return;
      }
      if (_reactNative.Platform.OS === 'android') {
        const saf = FileSystem.StorageAccessFramework;
        let dirUri = safDirUriRef.current;
        if (!dirUri) {
          const perm = await saf.requestDirectoryPermissionsAsync();
          if (!perm.granted) {
            _reactNative.Alert.alert('Permission Denied', 'Storage permission is required to save the file.');
            return;
          }
          dirUri = perm.directoryUri;
          safDirUriRef.current = dirUri;
        }
        const baseName = fileName.replace(/\.[^/.]+$/, '');
        const mime = activeFile.mimetype || 'application/octet-stream';
        const base64 = await FileSystem.readAsStringAsync(download.uri, {
          encoding: FileSystem.EncodingType.Base64
        });
        const destUri = await saf.createFileAsync(dirUri, baseName, mime);
        await FileSystem.writeAsStringAsync(destUri, base64, {
          encoding: FileSystem.EncodingType.Base64
        });
      }
      showToast({
        id: Date.now().toString(),
        title: 'Success',
        message: 'Save successful',
        type: 'success'
      });
    } catch (err) {
      console.error('Error saving file:', err);
      _reactNative.Alert.alert('Error', 'Failed to save the file.');
    }
  };
  const saveClick = async () => {
    if (activeFile.mimetype.startsWith('image/') || activeFile.mimetype.startsWith('video/')) {
      await saveToGallery();
    } else {
      await saveFileToDownloads();
    }
  };
  const closeModal = () => {
    dispatch((0, _chatSettingsSlice.setActiveFile)({
      fileName: '',
      fileURL: '',
      mimetype: ''
    }));
    handleCloseModal?.();
  };

  // NOTE: plain computed value, NOT useMemo. It sits AFTER the
  // `if (!activeFile) return` guard above, so as a hook it would run
  // conditionally (skipped when activeFile is null) — changing the hook
  // count between renders and throwing "rendered more hooks than during
  // the previous render", which crashed the modal the instant you tapped
  // a video/image to open it. Recomputing this on each render is cheap.
  const getMediaComponent = (() => {
    switch (true) {
      case activeFile.mimetype.startsWith('image/'):
        return /*#__PURE__*/(0, _jsxRuntime.jsx)(_MediaComponents.FullScreenImage, {
          source: {
            uri: activeFile.fileURL || 'https://as2.ftcdn.net/v2/jpg/02/51/95/53/1000_F_251955356_FAQH0U1y1TZw3ZcdPGybwUkH90a3VAhb.jpg'
          },
          resizeMode: "contain",
          accessibilityLabel: activeFile.fileName
        });
      case activeFile.mimetype.startsWith('video/'):
        return /*#__PURE__*/(0, _jsxRuntime.jsx)(ModalVideo, {
          uri: activeFile.fileURL
        });
      case activeFile.mimetype.includes('application/octet-stream'):
        return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
          style: {
            width: '100%',
            padding: 20,
            gap: 12,
            backgroundColor: '#FFF8ED',
            borderRadius: 16
          },
          children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
            style: {
              fontSize: 16,
              fontWeight: '600'
            },
            children: "Voice message"
          }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_AudioMessage.default, {
            src: activeFile.fileURL,
            mimeType: activeFile.mimetype,
            fileName: activeFile.fileName,
            originalName: activeFile.originalName,
            duration: activeFile.duration,
            waveForm: activeFile.waveForm
          })]
        });
      // Mirrors the MediaMessage heuristic: treat octet-stream voicemails
      // with audio-shaped filenames / URLs as audio so the preview shows
      // the player instead of an "Unsupported" card. Customer-reported
      // #9 voicemail fix — see isLikelyAudio in mimeToExtension.ts.
      case (0, _mimeToExtension.isLikelyAudio)(activeFile.mimetype, activeFile.fileName, activeFile.fileURL, {
        duration: activeFile.duration,
        waveForm: activeFile.waveForm,
        originalName: activeFile.originalName
      }):
        return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
          style: {
            width: '100%',
            padding: 20,
            gap: 12,
            backgroundColor: '#FFF8ED',
            borderRadius: 16
          },
          children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
            style: {
              fontSize: 16,
              fontWeight: '600'
            },
            children: (0, _mimeToExtension.ensureFilenameHasExtension)(activeFile.originalName || activeFile.fileName, activeFile.mimetype)
          }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_AudioMessage.default, {
            src: activeFile.fileURL,
            mimeType: activeFile.mimetype,
            fileName: activeFile.fileName,
            originalName: activeFile.originalName,
            duration: activeFile.duration,
            waveForm: activeFile.waveForm
          })]
        });
      case activeFile.mimetype === 'application/pdf':
        return /*#__PURE__*/(0, _jsxRuntime.jsx)(_PdfView.default, {
          pdfUrl: activeFile.fileURL
        });
      default:
        {
          const displayName = (0, _mimeToExtension.ensureFilenameHasExtension)(activeFile.fileName, activeFile.mimetype);
          // Office docs (.docx / .xlsx / .pptx / .doc / .xls / .ppt /
          // .txt / .csv / .rtf) → render inline via Google's gview embed
          // — fixes the "blank preview" complaint for docs (bug #9).
          if (isGviewPreviewable(activeFile.mimetype)) {
            return /*#__PURE__*/(0, _jsxRuntime.jsx)(_DocumentViewer.default, {
              url: activeFile.fileURL,
              fileName: displayName
            });
          }
          // True last-resort fallback for genuinely unrenderable types
          // (binary blobs, exotic MIMEs). Friendly info card with the
          // filename so the user can still download.
          return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
            style: {
              backgroundColor: '#FFF8ED',
              borderRadius: 16,
              padding: 20,
              gap: 8
            },
            children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
              style: {
                fontSize: 16,
                fontWeight: '600'
              },
              children: displayName
            }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
              style: {
                color: '#666'
              },
              children: activeFile.mimetype || 'unknown type'
            }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
              style: {
                marginTop: 8
              },
              children: "This file format can't be previewed inline. Tap the save icon above to download it."
            })]
          });
        }
    }
  })();
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_styledModalComponents.ModalContainerFullScreen, {
    children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_ModalHeaderComponent.default, {
      handleCloseModal: closeModal,
      headerTitle: 'File preview',
      rightMenu: /*#__PURE__*/(0, _jsxRuntime.jsx)(_jsxRuntime.Fragment, {
        children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Button.default, {
          onPress: saveClick,
          children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_icons.SaveIcon, {})
        })
      })
    }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_styledModalComponents.CenterContainer, {
      style: {
        display: 'flex',
        flex: 1,
        justifyContent: 'center',
        // NOTE: do NOT set overflow:'hidden' here — on Android it clips
        // hardware-accelerated children (expo-av Video TextureView and
        // react-native-webview) to nothing, so video/PDF/doc previews
        // render blank while plain <Image> survives.
        overflow: 'visible',
        padding: 16,
        paddingBottom: 48
      },
      children: getMediaComponent
    })]
  });
};
const styles = _reactNative.StyleSheet.create({
  playOverlay: {
    ..._reactNative.StyleSheet.absoluteFillObject,
    justifyContent: 'center',
    alignItems: 'center'
  },
  playButton: {
    width: 64,
    height: 64,
    borderRadius: 32,
    backgroundColor: 'rgba(0, 0, 0, 0.55)',
    justifyContent: 'center',
    alignItems: 'center'
  }
});
var _default = exports.default = FilePreviewModal;
//# sourceMappingURL=FilePreviewModal.js.map