"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.MEDIA_REMOVE_INSERTED = exports.MEDIA_PERSIST_SUCCESS = exports.MEDIA_PERSIST_REQUEST = exports.MEDIA_PERSIST_FAILURE = exports.MEDIA_LOAD_SUCCESS = exports.MEDIA_LOAD_REQUEST = exports.MEDIA_LOAD_FAILURE = exports.MEDIA_LIBRARY_OPEN = exports.MEDIA_LIBRARY_CREATE = exports.MEDIA_LIBRARY_CLOSE = exports.MEDIA_INSERT = exports.MEDIA_DISPLAY_URL_SUCCESS = exports.MEDIA_DISPLAY_URL_REQUEST = exports.MEDIA_DISPLAY_URL_FAILURE = exports.MEDIA_DELETE_SUCCESS = exports.MEDIA_DELETE_REQUEST = exports.MEDIA_DELETE_FAILURE = void 0;
exports.clearMediaControl = clearMediaControl;
exports.closeMediaLibrary = closeMediaLibrary;
exports.createMediaLibrary = createMediaLibrary;
exports.deleteMedia = deleteMedia;
exports.getMediaDisplayURL = getMediaDisplayURL;
exports.getMediaFile = getMediaFile;
exports.insertMedia = insertMedia;
exports.loadMedia = loadMedia;
exports.loadMediaDisplayURL = loadMediaDisplayURL;
exports.mediaDeleteFailed = mediaDeleteFailed;
exports.mediaDeleted = mediaDeleted;
exports.mediaDeleting = mediaDeleting;
exports.mediaDisplayURLFailure = mediaDisplayURLFailure;
exports.mediaDisplayURLRequest = mediaDisplayURLRequest;
exports.mediaDisplayURLSuccess = mediaDisplayURLSuccess;
exports.mediaLoadFailed = mediaLoadFailed;
exports.mediaLoaded = mediaLoaded;
exports.mediaLoading = mediaLoading;
exports.mediaPersistFailed = mediaPersistFailed;
exports.mediaPersisted = mediaPersisted;
exports.mediaPersisting = mediaPersisting;
exports.openMediaLibrary = openMediaLibrary;
exports.persistMedia = persistMedia;
exports.removeInsertedMedia = removeInsertedMedia;
exports.removeMediaControl = removeMediaControl;
exports.waitForMediaLibraryToLoad = waitForMediaLibraryToLoad;
var _immutable = require("immutable");
var _decapCmsLibUtil = require("decap-cms-lib-util");
var _backend = require("../backend");
var _AssetProxy = require("../valueObjects/AssetProxy");
var _reducers = require("../reducers");
var _entries = require("../reducers/entries");
var _mediaLibrary = require("../reducers/mediaLibrary");
var _integrations = require("../integrations");
var _media = require("./media");
var _entries2 = require("./entries");
var _urlHelper = require("../lib/urlHelper");
var _waitUntil = require("./waitUntil");
var _notifications = require("./notifications");
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : String(i); }
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
const MEDIA_LIBRARY_OPEN = exports.MEDIA_LIBRARY_OPEN = 'MEDIA_LIBRARY_OPEN';
const MEDIA_LIBRARY_CLOSE = exports.MEDIA_LIBRARY_CLOSE = 'MEDIA_LIBRARY_CLOSE';
const MEDIA_LIBRARY_CREATE = exports.MEDIA_LIBRARY_CREATE = 'MEDIA_LIBRARY_CREATE';
const MEDIA_INSERT = exports.MEDIA_INSERT = 'MEDIA_INSERT';
const MEDIA_REMOVE_INSERTED = exports.MEDIA_REMOVE_INSERTED = 'MEDIA_REMOVE_INSERTED';
const MEDIA_LOAD_REQUEST = exports.MEDIA_LOAD_REQUEST = 'MEDIA_LOAD_REQUEST';
const MEDIA_LOAD_SUCCESS = exports.MEDIA_LOAD_SUCCESS = 'MEDIA_LOAD_SUCCESS';
const MEDIA_LOAD_FAILURE = exports.MEDIA_LOAD_FAILURE = 'MEDIA_LOAD_FAILURE';
const MEDIA_PERSIST_REQUEST = exports.MEDIA_PERSIST_REQUEST = 'MEDIA_PERSIST_REQUEST';
const MEDIA_PERSIST_SUCCESS = exports.MEDIA_PERSIST_SUCCESS = 'MEDIA_PERSIST_SUCCESS';
const MEDIA_PERSIST_FAILURE = exports.MEDIA_PERSIST_FAILURE = 'MEDIA_PERSIST_FAILURE';
const MEDIA_DELETE_REQUEST = exports.MEDIA_DELETE_REQUEST = 'MEDIA_DELETE_REQUEST';
const MEDIA_DELETE_SUCCESS = exports.MEDIA_DELETE_SUCCESS = 'MEDIA_DELETE_SUCCESS';
const MEDIA_DELETE_FAILURE = exports.MEDIA_DELETE_FAILURE = 'MEDIA_DELETE_FAILURE';
const MEDIA_DISPLAY_URL_REQUEST = exports.MEDIA_DISPLAY_URL_REQUEST = 'MEDIA_DISPLAY_URL_REQUEST';
const MEDIA_DISPLAY_URL_SUCCESS = exports.MEDIA_DISPLAY_URL_SUCCESS = 'MEDIA_DISPLAY_URL_SUCCESS';
const MEDIA_DISPLAY_URL_FAILURE = exports.MEDIA_DISPLAY_URL_FAILURE = 'MEDIA_DISPLAY_URL_FAILURE';
function createMediaLibrary(instance) {
  const api = {
    show: instance.show || (() => undefined),
    hide: instance.hide || (() => undefined),
    onClearControl: instance.onClearControl || (() => undefined),
    onRemoveControl: instance.onRemoveControl || (() => undefined),
    enableStandalone: instance.enableStandalone || (() => undefined)
  };
  return {
    type: MEDIA_LIBRARY_CREATE,
    payload: api
  };
}
function clearMediaControl(id) {
  return (_dispatch, getState) => {
    const state = getState();
    const mediaLibrary = state.mediaLibrary.get('externalLibrary');
    if (mediaLibrary) {
      mediaLibrary.onClearControl({
        id
      });
    }
  };
}
function removeMediaControl(id) {
  return (_dispatch, getState) => {
    const state = getState();
    const mediaLibrary = state.mediaLibrary.get('externalLibrary');
    if (mediaLibrary) {
      mediaLibrary.onRemoveControl({
        id
      });
    }
  };
}
function openMediaLibrary(payload = {}) {
  return (dispatch, getState) => {
    const state = getState();
    const mediaLibrary = state.mediaLibrary.get('externalLibrary');
    if (mediaLibrary) {
      const {
        controlID: id,
        value,
        config = (0, _immutable.Map)(),
        allowMultiple,
        forImage
      } = payload;
      mediaLibrary.show({
        id,
        value,
        config: config.toJS(),
        allowMultiple,
        imagesOnly: forImage
      });
    }
    dispatch(mediaLibraryOpened(payload));
  };
}
function closeMediaLibrary() {
  return (dispatch, getState) => {
    const state = getState();
    const mediaLibrary = state.mediaLibrary.get('externalLibrary');
    if (mediaLibrary) {
      mediaLibrary.hide();
    }
    dispatch(mediaLibraryClosed());
  };
}
function insertMedia(mediaPath, field) {
  return (dispatch, getState) => {
    const state = getState();
    const config = state.config;
    const entry = state.entryDraft.get('entry');
    const collectionName = state.entryDraft.getIn(['entry', 'collection']);
    const collection = state.collections.get(collectionName);
    if (Array.isArray(mediaPath)) {
      mediaPath = mediaPath.map(path => (0, _entries.selectMediaFilePublicPath)(config, collection, path, entry, field));
    } else {
      mediaPath = (0, _entries.selectMediaFilePublicPath)(config, collection, mediaPath, entry, field);
    }
    dispatch(mediaInserted(mediaPath));
  };
}
function removeInsertedMedia(controlID) {
  return {
    type: MEDIA_REMOVE_INSERTED,
    payload: {
      controlID
    }
  };
}
function loadMedia(opts = {}) {
  const {
    delay = 0,
    query = '',
    page = 1,
    privateUpload
  } = opts;
  return async (dispatch, getState) => {
    const state = getState();
    const backend = (0, _backend.currentBackend)(state.config);
    const integration = (0, _reducers.selectIntegration)(state, null, 'assetStore');
    if (integration) {
      const provider = (0, _integrations.getIntegrationProvider)(state.integrations, backend.getToken, integration);
      dispatch(mediaLoading(page));
      try {
        const files = await provider.retrieve(query, page, privateUpload);
        const mediaLoadedOpts = {
          page,
          canPaginate: true,
          dynamicSearch: true,
          dynamicSearchQuery: query,
          privateUpload
        };
        return dispatch(mediaLoaded(files, mediaLoadedOpts));
      } catch (error) {
        return dispatch(mediaLoadFailed({
          privateUpload
        }));
      }
    }
    dispatch(mediaLoading(page));
    function loadFunction() {
      return backend.getMedia().then(files => dispatch(mediaLoaded(files))).catch(error => {
        console.error(error);
        if (error.status === 404) {
          console.log('This 404 was expected and handled appropriately.');
          dispatch(mediaLoaded([]));
        } else {
          dispatch(mediaLoadFailed());
        }
      });
    }
    if (delay > 0) {
      return new Promise(resolve => {
        setTimeout(() => resolve(loadFunction()), delay);
      });
    } else {
      return loadFunction();
    }
  };
}
function createMediaFileFromAsset({
  id,
  file,
  assetProxy,
  draft
}) {
  const mediaFile = {
    id,
    name: (0, _decapCmsLibUtil.basename)(assetProxy.path),
    displayURL: assetProxy.url,
    draft,
    file,
    size: file.size,
    url: assetProxy.url,
    path: assetProxy.path,
    field: assetProxy.field
  };
  return mediaFile;
}
function persistMedia(file, opts = {}) {
  const {
    privateUpload,
    field
  } = opts;
  return async (dispatch, getState) => {
    const state = getState();
    const backend = (0, _backend.currentBackend)(state.config);
    const integration = (0, _reducers.selectIntegration)(state, null, 'assetStore');
    const files = (0, _mediaLibrary.selectMediaFiles)(state, field);
    const fileName = (0, _urlHelper.sanitizeSlug)(file.name.toLowerCase(), state.config.slug);
    const existingFile = files.find(existingFile => existingFile.name.toLowerCase() === fileName);
    const editingDraft = (0, _entries.selectEditingDraft)(state.entryDraft);

    /**
     * Check for existing files of the same name before persisting. If no asset
     * store integration is used, files are being stored in Git, so we can
     * expect file names to be unique. If an asset store is in use, file names
     * may not be unique, so we forego this check.
     */
    if (!integration && existingFile) {
      if (!window.confirm(`${existingFile.name} already exists. Do you want to replace it?`)) {
        return;
      } else {
        await dispatch(deleteMedia(existingFile, {
          privateUpload
        }));
      }
    }
    if (integration || !editingDraft) {
      dispatch(mediaPersisting());
    }
    try {
      let assetProxy;
      if (integration) {
        try {
          const provider = (0, _integrations.getIntegrationProvider)(state.integrations, backend.getToken, integration);
          const response = await provider.upload(file, privateUpload);
          assetProxy = (0, _AssetProxy.createAssetProxy)({
            url: response.asset.url,
            path: response.asset.url
          });
        } catch (error) {
          assetProxy = (0, _AssetProxy.createAssetProxy)({
            file,
            path: fileName
          });
        }
      } else if (privateUpload) {
        throw new Error('The Private Upload option is only available for Asset Store Integration');
      } else {
        const entry = state.entryDraft.get('entry');
        const collection = state.collections.get(entry === null || entry === void 0 ? void 0 : entry.get('collection'));
        const path = (0, _entries.selectMediaFilePath)(state.config, collection, entry, fileName, field);
        assetProxy = (0, _AssetProxy.createAssetProxy)({
          file,
          path,
          field
        });
      }
      dispatch((0, _media.addAsset)(assetProxy));
      let mediaFile;
      if (integration) {
        const id = await (0, _decapCmsLibUtil.getBlobSHA)(file);
        // integration assets are persisted immediately, thus draft is false
        mediaFile = createMediaFileFromAsset({
          id,
          file,
          assetProxy,
          draft: false
        });
      } else if (editingDraft) {
        const id = await (0, _decapCmsLibUtil.getBlobSHA)(file);
        mediaFile = createMediaFileFromAsset({
          id,
          file,
          assetProxy,
          draft: editingDraft
        });
        return dispatch((0, _entries2.addDraftEntryMediaFile)(mediaFile));
      } else {
        mediaFile = await backend.persistMedia(state.config, assetProxy);
      }
      return dispatch(mediaPersisted(mediaFile, {
        privateUpload
      }));
    } catch (error) {
      console.error(error);
      dispatch((0, _notifications.addNotification)({
        message: `Failed to persist media: ${error}`,
        type: 'error',
        dismissAfter: 8000
      }));
      return dispatch(mediaPersistFailed({
        privateUpload
      }));
    }
  };
}
function deleteMedia(file, opts = {}) {
  const {
    privateUpload
  } = opts;
  return async (dispatch, getState) => {
    const state = getState();
    const backend = (0, _backend.currentBackend)(state.config);
    const integration = (0, _reducers.selectIntegration)(state, null, 'assetStore');
    if (integration) {
      const provider = (0, _integrations.getIntegrationProvider)(state.integrations, backend.getToken, integration);
      dispatch(mediaDeleting());
      try {
        await provider.delete(file.id);
        return dispatch(mediaDeleted(file, {
          privateUpload
        }));
      } catch (error) {
        console.error(error);
        dispatch((0, _notifications.addNotification)({
          message: `Failed to delete media: ${error.message}`,
          type: 'error',
          dismissAfter: 8000
        }));
        return dispatch(mediaDeleteFailed({
          privateUpload
        }));
      }
    }
    try {
      if (file.draft) {
        dispatch((0, _media.removeAsset)(file.path));
        dispatch((0, _entries2.removeDraftEntryMediaFile)({
          id: file.id
        }));
      } else {
        const editingDraft = (0, _entries.selectEditingDraft)(state.entryDraft);
        dispatch(mediaDeleting());
        dispatch((0, _media.removeAsset)(file.path));
        await backend.deleteMedia(state.config, file.path);
        dispatch(mediaDeleted(file));
        if (editingDraft) {
          dispatch((0, _entries2.removeDraftEntryMediaFile)({
            id: file.id
          }));
        }
      }
    } catch (error) {
      console.error(error);
      dispatch((0, _notifications.addNotification)({
        message: `Failed to delete media: ${error.message}`,
        type: 'error',
        dismissAfter: 8000
      }));
      return dispatch(mediaDeleteFailed());
    }
  };
}
async function getMediaFile(state, path) {
  const backend = (0, _backend.currentBackend)(state.config);
  const {
    url
  } = await backend.getMediaFile(path);
  return {
    url
  };
}
function loadMediaDisplayURL(file) {
  return async (dispatch, getState) => {
    const {
      displayURL,
      id
    } = file;
    const state = getState();
    const displayURLState = (0, _mediaLibrary.selectMediaDisplayURL)(state, id);
    if (!id || !displayURL || displayURLState.get('url') || displayURLState.get('isFetching') || displayURLState.get('err')) {
      return Promise.resolve();
    }
    if (typeof displayURL === 'string') {
      dispatch(mediaDisplayURLRequest(id));
      dispatch(mediaDisplayURLSuccess(id, displayURL));
      return;
    }
    try {
      const backend = (0, _backend.currentBackend)(state.config);
      dispatch(mediaDisplayURLRequest(id));
      const newURL = await backend.getMediaDisplayURL(displayURL);
      if (newURL) {
        dispatch(mediaDisplayURLSuccess(id, newURL));
      } else {
        throw new Error('No display URL was returned!');
      }
    } catch (err) {
      console.error(err);
      dispatch(mediaDisplayURLFailure(id, err));
    }
  };
}
function mediaLibraryOpened(payload) {
  return {
    type: MEDIA_LIBRARY_OPEN,
    payload
  };
}
function mediaLibraryClosed() {
  return {
    type: MEDIA_LIBRARY_CLOSE
  };
}
function mediaInserted(mediaPath) {
  return {
    type: MEDIA_INSERT,
    payload: {
      mediaPath
    }
  };
}
function mediaLoading(page) {
  return {
    type: MEDIA_LOAD_REQUEST,
    payload: {
      page
    }
  };
}
function mediaLoaded(files, opts = {}) {
  return {
    type: MEDIA_LOAD_SUCCESS,
    payload: _objectSpread({
      files
    }, opts)
  };
}
function mediaLoadFailed(opts = {}) {
  const {
    privateUpload
  } = opts;
  return {
    type: MEDIA_LOAD_FAILURE,
    payload: {
      privateUpload
    }
  };
}
function mediaPersisting() {
  return {
    type: MEDIA_PERSIST_REQUEST
  };
}
function mediaPersisted(file, opts = {}) {
  const {
    privateUpload
  } = opts;
  return {
    type: MEDIA_PERSIST_SUCCESS,
    payload: {
      file,
      privateUpload
    }
  };
}
function mediaPersistFailed(opts = {}) {
  const {
    privateUpload
  } = opts;
  return {
    type: MEDIA_PERSIST_FAILURE,
    payload: {
      privateUpload
    }
  };
}
function mediaDeleting() {
  return {
    type: MEDIA_DELETE_REQUEST
  };
}
function mediaDeleted(file, opts = {}) {
  const {
    privateUpload
  } = opts;
  return {
    type: MEDIA_DELETE_SUCCESS,
    payload: {
      file,
      privateUpload
    }
  };
}
function mediaDeleteFailed(opts = {}) {
  const {
    privateUpload
  } = opts;
  return {
    type: MEDIA_DELETE_FAILURE,
    payload: {
      privateUpload
    }
  };
}
function mediaDisplayURLRequest(key) {
  return {
    type: MEDIA_DISPLAY_URL_REQUEST,
    payload: {
      key
    }
  };
}
function mediaDisplayURLSuccess(key, url) {
  return {
    type: MEDIA_DISPLAY_URL_SUCCESS,
    payload: {
      key,
      url
    }
  };
}
function mediaDisplayURLFailure(key, err) {
  return {
    type: MEDIA_DISPLAY_URL_FAILURE,
    payload: {
      key,
      err
    }
  };
}
async function waitForMediaLibraryToLoad(dispatch, state) {
  if (state.mediaLibrary.get('isLoading') !== false && !state.mediaLibrary.get('externalLibrary')) {
    await (0, _waitUntil.waitUntilWithTimeout)(dispatch, resolve => ({
      predicate: ({
        type
      }) => type === MEDIA_LOAD_SUCCESS || type === MEDIA_LOAD_FAILURE,
      run: () => resolve()
    }));
  }
}
async function getMediaDisplayURL(dispatch, state, file) {
  const displayURLState = (0, _mediaLibrary.selectMediaDisplayURL)(state, file.id);
  let url;
  if (displayURLState.get('url')) {
    // url was already loaded
    url = displayURLState.get('url');
  } else if (displayURLState.get('err')) {
    // url loading had an error
    url = null;
  } else {
    var _await$promise;
    const key = file.id;
    const promise = (0, _waitUntil.waitUntilWithTimeout)(dispatch, resolve => ({
      predicate: ({
        type,
        payload
      }) => (type === MEDIA_DISPLAY_URL_SUCCESS || type === MEDIA_DISPLAY_URL_FAILURE) && payload.key === key,
      run: (_dispatch, _getState, action) => resolve(action.payload.url)
    }));
    if (!displayURLState.get('isFetching')) {
      // load display url
      dispatch(loadMediaDisplayURL(file));
    }
    url = (_await$promise = await promise) !== null && _await$promise !== void 0 ? _await$promise : null;
  }
  return url;
}