"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
exports.__esModule = true;
exports.ViewsState = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _bexCore = require("@wix/bex-core");
var _mobx = require("mobx");
var _events = require("@wix/bex-core/events");
var _services = require("../services");
var _uuid = require("uuid");
var _model = require("../model");
var _AutoCompleteReadonlyState = require("../components/CollectionViewsDropdown/AutoCompleteReadonlyState");
var _ViewsLocalSearchState = require("./ViewsLocalSearchState");
const MAX_SAVED_VIEWS = 50;
const updatePresetViews = (presets, hiddenPresetIds) => {
  return presets.reduce((views, cat, ind) => {
    var _cat$views;
    return [...views, ...(((_cat$views = cat.views) == null ? void 0 : _cat$views.filter(p => !hiddenPresetIds.includes(p.id)).map(({
      isDefaultView,
      ...p
    }) => ({
      ...p,
      categoryId: cat.id,
      categorySortInd: `${ind + +_model.PREDEFINED_VIEWS_SORT_IND}`,
      isPreset: true
    }))) ?? [])];
  }, []);
};
const toNonPresetViews = (views, categoryId) => {
  return views.map(v => ({
    ...v,
    categoryId,
    isPreset: false,
    categorySortInd: _model.SAVED_VIEWS_SORT_IND
  }));
};
const getBasicCategories = presets => {
  return {
    [_model.SAVED_VIEWS_ID]: {
      id: _model.SAVED_VIEWS_ID,
      name: ''
    },
    ...presets.reduce((prev, {
      views,
      ...basicCategory
    }) => ({
      ...prev,
      [basicCategory.id]: basicCategory
    }), {})
  };
};
class ViewsState {
  constructor(params) {
    (0, _defineProperty2.default)(this, "currentView", void 0);
    (0, _defineProperty2.default)(this, "defaultViewId", void 0);
    (0, _defineProperty2.default)(this, "_initialViewIdFromUrl", void 0);
    (0, _defineProperty2.default)(this, "initialSelect", void 0);
    (0, _defineProperty2.default)(this, "viewsService", void 0);
    (0, _defineProperty2.default)(this, "collection", void 0);
    (0, _defineProperty2.default)(this, "optimisticActions", void 0);
    (0, _defineProperty2.default)(this, "saveViewModal", new _bexCore.ModalState());
    (0, _defineProperty2.default)(this, "renameViewModal", new _bexCore.ModalState());
    (0, _defineProperty2.default)(this, "autoCompleteReadonlyState", new _AutoCompleteReadonlyState.AutoCompleteReadonlyState());
    (0, _defineProperty2.default)(this, "localSearchState", void 0);
    (0, _defineProperty2.default)(this, "reportBI", void 0);
    (0, _defineProperty2.default)(this, "events", new _events.EventEmitter());
    (0, _defineProperty2.default)(this, "presets", void 0);
    (0, _defineProperty2.default)(this, "allItemsViewProps", void 0);
    (0, _defineProperty2.default)(this, "basicCategories", void 0);
    (0, _defineProperty2.default)(this, "initTask", new _bexCore.TaskState());
    (0, _defineProperty2.default)(this, "container", void 0);
    (0, _defineProperty2.default)(this, "_migrateOrdersViews", void 0);
    (0, _defineProperty2.default)(this, "_fixMissingContactsViews", void 0);
    const {
      container,
      fqdn,
      reportBI
    } = params;
    this.container = container;
    this.reportBI = reportBI;
    this.initialSelect = params.initialSelect;
    this.presets = params.presets ?? [];
    this.allItemsViewProps = params.allItemsViewProps ?? {};
    const viewsStorage = container._createComponentSettings({
      namespace: 'cairo'
    });
    const {
      environment
    } = container;
    const defaultViewStorage = environment.providerType === 'bm' ? viewsStorage : container.createEssentials({
      dataCapsule: {
        namespace: 'cairo',
        scope: environment.componentId,
        storageStrategy: environment.providerType === 'giza' ? 'userPreferences' : undefined
      }
    }).dataCapsule;
    this.viewsService = new _services.ViewsService({
      viewsStorage,
      defaultViewStorage,
      fqdn,
      monitor: container.internalMonitor,
      errorHandler: container.errorHandler,
      translate: container.translate
    });
    this.collection = new _bexCore.CollectionState({
      ...container,
      events: {},
      queryName: [fqdn, 'views'].join('/'),
      fetchData: async () => {
        const {
          viewsService,
          collection,
          allItemsViewProps
        } = this;
        if (collection.initTask.status.isLoading) {
          var _this$_migrateOrdersV, _this$_fixMissingCont;
          await viewsService.migrateFromLocalStorage();
          await ((_this$_migrateOrdersV = this._migrateOrdersViews) == null ? void 0 : _this$_migrateOrdersV.call(this, this));
          await ((_this$_fixMissingCont = this._fixMissingContactsViews) == null ? void 0 : _this$_fixMissingCont.call(this, this));
        }
        const result = await viewsService.fetchViews();
        const {
          views = [],
          hiddenPresetIds = []
        } = result ?? {};
        const items = [];
        if (!allItemsViewProps.hidden ||
        // we ignore the hidden flag if there are no presets
        this.presets.every(pr => {
          var _pr$views;
          return !((_pr$views = pr.views) != null && _pr$views.length);
        })) {
          items.push(await this.getAllItemsView(this.allItemsViewProps));
        }
        items.push(...(toNonPresetViews(views, _model.SAVED_VIEWS_ID) ?? []));
        items.push(...updatePresetViews(this.presets, hiddenPresetIds));
        return {
          items
        };
      },
      itemKey: ({
        id
      }) => id,
      itemName: ({
        name
      }) => name,
      filters: {}
    });
    this.localSearchState = new _ViewsLocalSearchState.ViewsLocalSearchState({
      views: this
    });
    this.optimisticActions = new _bexCore.CollectionOptimisticActions({
      container,
      collection: this.collection,
      orderBy: ({
        sort
      }) => [...(sort || []), {
        fieldName: item => item.categorySortInd,
        order: 'asc'
      }]
    });
    this.basicCategories = getBasicCategories(this.presets);
    this.currentView = null;
    this.defaultViewId = null;
    (0, _mobx.makeObservable)(this, {
      isReady: _mobx.computed,
      isDefaultView: _mobx.computed,
      currentView: _mobx.observable.ref,
      defaultViewId: _mobx.observable.ref,
      selectView: _mobx.action,
      unselectView: _mobx.action,
      setDefaultViewId: _mobx.action,
      _onActionUndo: _mobx.action,
      reachedViewsLimit: _mobx.computed,
      isCurrentViewSelected: _mobx.computed
    });
  }
  _getAllItemsAndPresetViews() {
    const {
      allItemsViewProps
    } = this;
    const items = [];
    if (!allItemsViewProps.hidden ||
    // we ignore the hidden flag if there are no presets
    this.presets.every(pr => {
      var _pr$views2;
      return !((_pr$views2 = pr.views) != null && _pr$views2.length);
    })) {
      items.push(this.getAllItemsViewBase(this.allItemsViewProps));
    }
    items.push(...updatePresetViews(this.presets, []));
    return items;
  }
  _getInitialSelectItem(items) {
    const {
      initialSelect,
      _initialViewIdFromUrl,
      defaultViewId
    } = this;
    if (initialSelect == null) {
      if (_initialViewIdFromUrl) {
        return items.find(item => item.id === _initialViewIdFromUrl);
      }
      if (defaultViewId) {
        return items.find(item => item.id === defaultViewId);
      }
      const defaultPresetId = this.getDefaultPreset() ?? _model.ALL_ITEMS_VIEW_ID;
      return items.find(item => item.id === defaultPresetId);
    }
    if (initialSelect === true) {
      return items[0];
    }
    return items.find((item, index) => initialSelect(item, index));
  }
  _onActionUndo(id, actionName, newName) {
    this.events.emit('undoAction', {
      actionName,
      viewId: id,
      newName
    });
    this.selectView({
      id,
      needFiltersReset: false
    });
  }
  _onTryAgain(actionName) {
    this.events.emit('tryAgainAction', {
      actionName
    });
  }
  _onError(actionName, createdAt, oldViewId, viewId) {
    if (oldViewId) {
      this.selectView({
        id: oldViewId,
        needFiltersReset: false
      });
    } else {
      this.unselectView();
    }
    this.events.emit('errorAction', {
      actionName,
      createdAt,
      viewId: viewId ?? oldViewId ?? ''
    });
  }
  init() {
    const {
      collection,
      localSearchState
    } = this;
    const disposers = [collection.init(), this.optimisticActions.init(), localSearchState.init()];
    this.initTask.runOnce(async () => {
      await collection.initTask.status.promise;
      this.setDefaultViewId(await this.viewsService.fetchDefaultViewId());
    });
    return () => {
      disposers.forEach(disposer => disposer());
    };
  }
  getViews() {
    return this.collection.result.items.slice();
  }
  getView(viewId) {
    return this.getViews().find(({
      id
    }) => id === viewId);
  }
  getDefaultPreset() {
    var _this$presets$reduce$;
    return (_this$presets$reduce$ = this.presets.reduce((prev, cur) => [...prev, ...cur.views], []).find(view => view.isDefaultView)) == null ? void 0 : _this$presets$reduce$.id;
  }
  get isDefaultView() {
    var _this$currentView;
    return ((_this$currentView = this.currentView) == null ? void 0 : _this$currentView.id) === this.defaultViewId;
  }
  async getAllItemsView(view) {
    const {
      container
    } = this;
    await container.initTask.status.promise;
    return {
      ...this.getAllItemsViewBase(view),
      name: view.name ?? container.translate('cairo.viewsDropdown.allItems.label')
    };
  }
  getAllItemsViewBase(view) {
    return {
      categorySortInd: _model.ALL_ITEMS_SORT_IND,
      id: _model.ALL_ITEMS_VIEW_ID,
      name: view.name ?? '',
      selectedColumns: view.selectedColumns,
      sortDirections: view.sortDirections,
      isPreset: true
    };
  }
  async saveViewChanges(viewBase) {
    if (!this.currentView) {
      return null;
    }
    const updatedView = {
      ...this.currentView,
      ...viewBase
    };
    return this.saveView({
      newView: updatedView,
      hasUndo: true,
      oldViewId: this.currentView.id
    });
  }
  createNewView(name, viewBase) {
    var _this$currentView2;
    return {
      ...viewBase,
      categorySortInd: _model.SAVED_VIEWS_SORT_IND,
      categoryId: _model.SAVED_VIEWS_ID,
      isPreset: false,
      name,
      id: (0, _uuid.v4)(),
      extra: (_this$currentView2 = this.currentView) == null ? void 0 : _this$currentView2.extra
    };
  }
  async saveView({
    newView,
    hasUndo = false,
    isNew = false,
    oldViewId
  }) {
    const createdAt = Date.now();
    const immediateAction = () => {
      this.selectView({
        id: newView.id
      });
    };
    this.optimisticActions.createOne(newView, {
      submit: async () => {
        await this.viewsService.saveView(newView);
        return [newView];
      },
      showUndoToast: hasUndo,
      onUndo: () => {
        this._onActionUndo(newView.id, isNew ? 'view-save-new' : 'view-save-changes');
      },
      onTryAgain: () => {
        immediateAction();
        this._onTryAgain(isNew ? 'view-save-new' : 'view-save-changes');
      },
      onError: _ => {
        this._onError(isNew ? 'view-save-new' : 'view-save-changes', createdAt, oldViewId, newView.id);
      },
      successToast: {
        biName: isNew ? 'cairo-save-new-view-success' : 'cairo-save-view-changes-success',
        message: isNew ? this.collection.translate('cairo.saveView.Success.toast', {
          viewName: newView.name
        }) : this.collection.translate('cairo.manageView.saveChanges.Success.toast', {
          viewName: newView.name
        })
      },
      errorToast: err => {
        var _this$container$error;
        const resolvedError = (_this$container$error = this.container.errorHandler) == null || _this$container$error.getResolvedError == null ? void 0 : _this$container$error.getResolvedError(err);
        return {
          biName: isNew ? 'cairo-save-new-view-error' : 'cairo-save-view-changes-error',
          message: resolvedError == null ? void 0 : resolvedError.message,
          ...(resolvedError != null && resolvedError.action ? {
            action: resolvedError == null ? void 0 : resolvedError.action
          } : {}),
          type: 'ERROR'
        };
      }
    });
    immediateAction();
    return newView;
  }
  async deleteView(view) {
    const {
      viewsService,
      currentView
    } = this;
    const {
      id,
      isPreset
    } = view;
    const isCurrentViewSelected = (currentView == null ? void 0 : currentView.id) === id;
    const idForUndo = currentView == null ? void 0 : currentView.id;
    const prevDefaultView = this.defaultViewId;
    const createdAt = Date.now();
    const immediateAction = async () => {
      if (id === this.defaultViewId) {
        await this.viewsService.updateDefaultView(undefined);
        this.setDefaultViewId(null);
      }
      if (isCurrentViewSelected) {
        this.unselectView();
      }
    };
    this.optimisticActions.deleteOne(view, {
      submit: async () => {
        if (isPreset) {
          await viewsService.updateHiddenPreset(id);
        } else {
          await viewsService.deleteView(view);
        }
      },
      onUndo: () => {
        if (!idForUndo) {
          return;
        }
        this.setDefaultViewId(prevDefaultView);
        this._onActionUndo(idForUndo, 'view-delete');
      },
      onTryAgain: async () => {
        await immediateAction();
        this._onTryAgain('view-delete');
      },
      onError: _ => {
        this.setDefaultViewId(prevDefaultView);
        this._onError('view-delete', createdAt, idForUndo);
      },
      showUndoToast: true,
      successToast: {
        biName: 'cairo-delete-view-success',
        message: this.collection.translate('cairo.deleteView.Success.toast', {
          viewName: view.name
        })
      },
      errorToast: err => {
        var _this$container$error2;
        const resolvedError = (_this$container$error2 = this.container.errorHandler) == null || _this$container$error2.getResolvedError == null ? void 0 : _this$container$error2.getResolvedError(err);
        return {
          biName: 'cairo-delete-view-error',
          message: resolvedError == null ? void 0 : resolvedError.message,
          ...(resolvedError != null && resolvedError.action ? {
            action: resolvedError == null ? void 0 : resolvedError.action
          } : {}),
          type: 'ERROR'
        };
      }
    });
    immediateAction();
    return;
  }
  async renameView(newView, oldName) {
    const createdAt = Date.now();
    const immediateAction = () => {
      this.selectView({
        id: newView.id
      });
    };
    this.optimisticActions.createOne(newView, {
      submit: async () => {
        await this.viewsService.saveView(newView, {
          isRename: true
        });
        return [newView];
      },
      onUndo: () => {
        this._onActionUndo(newView.id, 'view-rename', newView.name);
      },
      onTryAgain: () => {
        immediateAction();
        this._onTryAgain('view-rename');
      },
      onError: _ => {
        this._onError('view-rename', createdAt, newView.id);
      },
      showUndoToast: true,
      successToast: {
        biName: 'cairo-rename-view-success',
        message: this.collection.translate('cairo.manageView.Rename.Success.toast', {
          oldViewName: oldName,
          newViewName: newView.name
        })
      },
      errorToast: err => {
        var _this$container$error3;
        const resolvedError = (_this$container$error3 = this.container.errorHandler) == null || _this$container$error3.getResolvedError == null ? void 0 : _this$container$error3.getResolvedError(err);
        return {
          biName: 'cairo-rename-view-error',
          message: resolvedError == null ? void 0 : resolvedError.message,
          ...(resolvedError != null && resolvedError.action ? {
            action: resolvedError == null ? void 0 : resolvedError.action
          } : {}),
          type: 'ERROR'
        };
      }
    });
    immediateAction();
    return newView;
  }
  async setAsDefaultView(newView, isDefault) {
    const createdAt = Date.now();
    const prevDefaultView = this.defaultViewId;
    const biName = isDefault ? 'view-set-as-default' : 'view-unset-as-default';
    const immediateAction = () => {
      this.setDefaultViewId(isDefault ? newView.id : null);
    };
    this.optimisticActions.createOne(newView, {
      submit: async () => {
        await this.viewsService.updateDefaultView(isDefault ? newView : undefined);
        return [newView];
      },
      onUndo: () => {
        this.setDefaultViewId(prevDefaultView);
        this._onActionUndo(newView.id, biName);
      },
      onTryAgain: () => {
        immediateAction();
        this._onTryAgain(biName);
      },
      onError: _ => {
        this.setDefaultViewId(prevDefaultView);
        this._onError(biName, createdAt, newView.id);
      },
      showUndoToast: isDefault,
      successToast: isDefault ? {
        biName: 'cairo-set-default-view-success',
        message: this.collection.translate('cairo.manageView.setAsDefault.success.toast', {
          viewName: newView.name
        })
      } : undefined,
      errorToast: err => {
        var _this$container$error4;
        const resolvedError = (_this$container$error4 = this.container.errorHandler) == null || _this$container$error4.getResolvedError == null ? void 0 : _this$container$error4.getResolvedError(err);
        return {
          biName: 'cairo-set-default-view-error',
          message: (resolvedError == null ? void 0 : resolvedError.message) ?? this.collection.translate('cairo.manageView.setAsDefault.error.toast', {
            viewName: newView.name
          }),
          ...(resolvedError != null && resolvedError.action ? {
            action: resolvedError == null ? void 0 : resolvedError.action
          } : {}),
          type: 'ERROR'
        };
      }
    });
    immediateAction();
    return newView;
  }
  get isReady() {
    const {
      isError,
      isFetching,
      isSuccess
    } = this.collection.result.status;
    return !isError && !isFetching && isSuccess;
  }
  setDefaultViewId(defaultViewId) {
    this.defaultViewId = defaultViewId;
  }
  unselectView() {
    this.currentView = null;
  }
  selectView({
    id,
    needFiltersReset
  }) {
    const view = this.getView(id);
    this.currentView = view ?? null;
    this.events.emit('selectAndRefresh', needFiltersReset);
  }
  get reachedViewsLimit() {
    return this.getViews().filter(({
      isPreset
    }) => !isPreset).length >= MAX_SAVED_VIEWS;
  }
  get isCurrentViewSelected() {
    var _this$currentView3;
    return !!((_this$currentView3 = this.currentView) != null && _this$currentView3.id);
  }
  hasViewName(viewName) {
    return this.getViews().map(({
      name
    }) => name).includes(viewName);
  }
}
exports.ViewsState = ViewsState;
//# sourceMappingURL=ViewsState.js.map