"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
exports.__esModule = true;
exports.TagsBulkAssignAsyncState = exports.POLL_DELAY = exports.MILLIS_FOR_SHOWING_SUCCESS = exports.MAX_JOB_RETRIES_COUNT = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _bexCore = require("@wix/bex-core");
var _mobx = require("mobx");
var _http = require("@wix/bex-utils/@wix/ambassador-infra-asyncjobs-v1-async-job/http");
const POLL_DELAY = exports.POLL_DELAY = 500;
const MILLIS_FOR_SHOWING_SUCCESS = exports.MILLIS_FOR_SHOWING_SUCCESS = 1000;
const MAX_JOB_RETRIES_COUNT = exports.MAX_JOB_RETRIES_COUNT = 4;
class TagsBulkAssignAsyncState {
  constructor(params) {
    (0, _defineProperty2.default)(this, "collectionState", void 0);
    (0, _defineProperty2.default)(this, "optimisticActions", void 0);
    (0, _defineProperty2.default)(this, "container", void 0);
    (0, _defineProperty2.default)(this, "tagsBIReporter", void 0);
    (0, _defineProperty2.default)(this, "asyncBulkUpdateTags", void 0);
    (0, _defineProperty2.default)(this, "asyncJobProgressModalState", new _bexCore.ConditionalModalState());
    (0, _defineProperty2.default)(this, "job", null);
    (0, _defineProperty2.default)(this, "timeout", void 0);
    (0, _defineProperty2.default)(this, "isDuringApplyChanges", false);
    (0, _defineProperty2.default)(this, "currentInvocationParams", null);
    (0, _defineProperty2.default)(this, "updatingTagsToast", null);
    (0, _defineProperty2.default)(this, "getJobRetriesCount", 0);
    (0, _defineProperty2.default)(this, "openAsyncJobProgressModal", () => {
      this.asyncJobProgressModalState.modal.open();
    });
    (0, _defineProperty2.default)(this, "closeAsyncJobProgressModal", () => {
      this.asyncJobProgressModalState.modal.close();
      if (this.isJobInProgress) {
        var _this$container$showT, _this$container;
        this.updatingTagsToast = ((_this$container$showT = (_this$container = this.container).showToast) == null ? void 0 : _this$container$showT.call(_this$container, {
          type: 'STANDARD',
          message: this.container.translate('cairo.tags.bulkItemUpdate.updatingTags.toast'),
          action: {
            text: this.container.translate('cairo.tags.bulkItemUpdate.updatingTags.toast.CTA'),
            onClick: async () => {
              this.openAsyncJobProgressModal();
            },
            removeToastOnClick: true
          },
          timeout: 'NONE',
          biName: 'cairo-updating-bulk-assign-tags-async'
        })) || null;
      }
    });
    const {
      collectionState,
      optimisticActions,
      container,
      tagsBIReporter,
      asyncBulkUpdateTags
    } = params;
    this.collectionState = collectionState;
    this.optimisticActions = optimisticActions;
    this.container = container;
    this.tagsBIReporter = tagsBIReporter;
    this.asyncBulkUpdateTags = asyncBulkUpdateTags;
    (0, _mobx.makeObservable)(this, {
      job: _mobx.observable.ref,
      isDuringApplyChanges: _mobx.observable,
      init: _mobx.action,
      applyChanges: _mobx.action,
      pollJobStatus: _mobx.action,
      canBulkAssignAsync: _mobx.computed,
      isJobCompleted: _mobx.computed,
      isJobFailed: _mobx.computed,
      isJobEnded: _mobx.computed,
      isJobInProgress: _mobx.computed,
      updatedItemsPercentage: _mobx.computed
    });
  }
  init() {
    const {
      onBeforeUnload
    } = this.container;
    const onBeforeUnloadSubscription = onBeforeUnload == null ? void 0 : onBeforeUnload((0, _mobx.action)(event => {
      if (this.isDuringApplyChanges) {
        event.preventDefault();
      }
    }));
    const disposers = [() => {
      onBeforeUnloadSubscription == null || onBeforeUnloadSubscription.remove();
    }, () => {
      if (this.timeout) {
        window.clearTimeout(this.timeout);
      }
    }];
    return () => {
      disposers.forEach(disposer => disposer());
    };
  }
  async applyChanges({
    newAssignedTagIds,
    newUnassignedTagIds
  }) {
    this.isDuringApplyChanges = true;
    const {
      bulkSelect,
      result
    } = this.collectionState;
    const {
      allSelected,
      selectedValues,
      uncheckedValues
    } = bulkSelect;
    const params = {
      allSelected,
      selectedValues,
      uncheckedValues,
      query: result.originQuery,
      assignTags: {
        privateTags: {
          tagIds: newAssignedTagIds
        }
      },
      unassignTags: {
        privateTags: {
          tagIds: newUnassignedTagIds
        }
      }
    };
    await this.triggerBulkAssign(params);
  }
  async triggerBulkAssign(params) {
    if (!this.asyncBulkUpdateTags) {
      throw new Error('tried to bulk assign tags async without asyncBulkUpdateTags prop given');
    }
    this.currentInvocationParams = params;
    try {
      await this.startTagUpdateProcess(params);
    } catch (error) {
      this.showFailToCreateJobToast(error);
      this.resetStateParams();
    }
  }
  async startTagUpdateProcess(params) {
    this.openAsyncJobProgressModal();
    const {
      jobId
    } = await this.asyncBulkUpdateTags(params);
    await this.pollJobStatus(jobId);
  }
  async pollJobStatus(jobId) {
    let job = null;
    try {
      job = await this.fetchJobStatus(jobId);
    } catch (error) {
      this.handlePollingError(error);
      return;
    }
    (0, _mobx.runInAction)(() => {
      this.job = job;
      if (this.isJobInProgress || !job) {
        this.scheduleNextPoll(jobId);
      } else if (this.isJobEnded) {
        this.handleJobEnd();
      }
    });
  }
  handlePollingError(error) {
    this.asyncJobProgressModalState.modal.close();
    this.showFailedToPollToast(error);
    this.resetStateParams();
  }
  async fetchJobStatus(jobId) {
    try {
      const {
        data: {
          job
        }
      } = await this.container.errorHandler.withErrorHandler(() => this.container.httpClient.request((0, _http.getAsyncJob)({
        jobId
      })), {});
      this.getJobRetriesCount = 0;
      return job;
    } catch (error) {
      var _this$container$error, _this$container$error2;
      if (this.getJobRetriesCount >= MAX_JOB_RETRIES_COUNT) {
        throw new _bexCore.WixPatternsError({
          originalException: error,
          errorCode: 'BulkAssignTagsFailed'
        });
      }
      (_this$container$error = (_this$container$error2 = this.container.errorHandler).reportRetryAttempt) == null || _this$container$error.call(_this$container$error2, error);
      this.getJobRetriesCount++;
      return null;
    }
  }
  scheduleNextPoll(jobId) {
    this.timeout = window.setTimeout(() => {
      (0, _mobx.runInAction)(() => this.pollJobStatus(jobId));
    }, POLL_DELAY);
  }
  handleJobEnd() {
    this.timeout = window.setTimeout(() => {
      (0, _mobx.runInAction)(() => {
        this.scheduleJobCompletionHandling();
      });
    }, MILLIS_FOR_SHOWING_SUCCESS);
  }
  scheduleJobCompletionHandling() {
    const lastInvocationParams = this.currentInvocationParams;
    const {
      showToast,
      translate: t
    } = this.container;
    if (this.isJobCompleted) {
      this.handleJobSuccess(lastInvocationParams);
    } else if (this.isJobFailed) {
      var _this$job;
      showToast == null || showToast({
        type: 'ERROR',
        message: t('cairo.tags.bulkItemUpdate.toast.error', {
          total: (_this$job = this.job) == null || (_this$job = _this$job.counts) == null ? void 0 : _this$job.failCount
        }),
        biName: 'cairo-update-bulk-assign-tags-async-job-status-fail'
      });
    }
    this.resetStateParams();
  }
  handleJobSuccess(lastInvocationParams) {
    var _this$job2;
    const failCount = (_this$job2 = this.job) == null || (_this$job2 = _this$job2.counts) == null ? void 0 : _this$job2.failCount;
    if (failCount) {
      this.showPartialFailureToast({
        failCount,
        lastInvocationParams
      });
    }
    this.showJobCompletedSuccessfullyToast();
    this.refreshCollection();
  }
  resetStateParams() {
    var _this$updatingTagsToa;
    this.getJobRetriesCount = 0;
    this.job = null;
    this.currentInvocationParams = null;
    this.isDuringApplyChanges = false;
    (_this$updatingTagsToa = this.updatingTagsToast) == null || _this$updatingTagsToa.remove();
    this.updatingTagsToast = null;
    this.closeAsyncJobProgressModal();
  }
  showPartialFailureToast({
    failCount,
    lastInvocationParams
  }) {
    var _this$container$showT2, _this$container2;
    (_this$container$showT2 = (_this$container2 = this.container).showToast) == null || _this$container$showT2.call(_this$container2, {
      type: 'WARNING',
      message: this.container.translate('cairo.tags.bulkItemUpdate.toast.error', {
        total: failCount
      }),
      action: {
        text: this.container.translate('cairo.tags.bulkItemUpdate.toast.error.CTA'),
        onClick: async () => {
          if (lastInvocationParams) {
            await this.triggerBulkAssign(lastInvocationParams);
          }
        },
        removeToastOnClick: true
      },
      biName: 'cairo-update-bulk-assign-tags-async-fail'
    });
  }
  showJobCompletedSuccessfullyToast() {
    var _this$container$showT3, _this$container3;
    (_this$container$showT3 = (_this$container3 = this.container).showToast) == null || _this$container$showT3.call(_this$container3, {
      type: 'SUCCESS',
      message: this.container.translate('cairo.tags.bulkItemUpdate.toast.success'),
      biName: 'cairo-update-bulk-assign-tags-async-success'
    });
  }
  showFailToCreateJobToast(error) {
    const {
      errorHandler,
      showToast,
      translate: t
    } = this.container;
    const resolvedError = errorHandler == null || errorHandler.getResolvedError == null ? void 0 : errorHandler.getResolvedError(error);
    showToast == null || showToast({
      type: 'ERROR',
      message: (resolvedError == null ? void 0 : resolvedError.message) ?? t('cairo.tags.bulkItemUpdate.toast.error', {
        total: this.collectionState.bulkSelect.selectedCountOrTotal
      }),
      action: resolvedError == null ? void 0 : resolvedError.action,
      biName: 'cairo-update-bulk-assign-tags-async-create-job-fail',
      details: resolvedError != null && resolvedError.requestId ? {
        requestId: resolvedError.requestId
      } : undefined
    });
  }
  showFailedToPollToast(error) {
    const {
      errorHandler,
      showToast
    } = this.container;
    const resolvedError = errorHandler == null || errorHandler.getResolvedError == null ? void 0 : errorHandler.getResolvedError(error);
    showToast == null || showToast({
      type: 'ERROR',
      message: resolvedError == null ? void 0 : resolvedError.message,
      action: resolvedError == null ? void 0 : resolvedError.action,
      biName: 'cairo-update-bulk-assign-tags-async-poll-fail',
      details: resolvedError != null && resolvedError.requestId ? {
        requestId: resolvedError.requestId
      } : undefined
    });
  }
  refreshCollection() {
    this.collectionState.refreshAllPages();
  }
  get isJobCompleted() {
    var _this$job3;
    return ((_this$job3 = this.job) == null ? void 0 : _this$job3.status) === 'FINISHED';
  }
  get isJobFailed() {
    var _this$job4;
    return ((_this$job4 = this.job) == null ? void 0 : _this$job4.status) === 'FAILED';
  }
  get isJobEnded() {
    return this.isJobCompleted || this.isJobFailed;
  }
  get isJobInProgress() {
    var _this$job5, _this$job6;
    return ((_this$job5 = this.job) == null ? void 0 : _this$job5.status) === 'PROCESSING' || ((_this$job6 = this.job) == null ? void 0 : _this$job6.status) === 'INITIALIZED';
  }
  get canBulkAssignAsync() {
    return !!this.asyncBulkUpdateTags;
  }
  get updatedItemsPercentage() {
    var _this$job$counts, _this$job$counts2, _this$job7;
    if (!this.job) {
      return 0;
    }
    const alreadyUpdatedItemsCount = (((_this$job$counts = this.job.counts) == null ? void 0 : _this$job$counts.successCount) || 0) + (((_this$job$counts2 = this.job.counts) == null ? void 0 : _this$job$counts2.failCount) || 0);
    const totalUpdatingItemsCount = ((_this$job7 = this.job) == null || (_this$job7 = _this$job7.counts) == null ? void 0 : _this$job7.total) || this.collectionState.bulkSelect.selectedCountOrTotal;
    return Math.floor(100 * (alreadyUpdatedItemsCount / totalUpdatingItemsCount));
  }
}
exports.TagsBulkAssignAsyncState = TagsBulkAssignAsyncState;
//# sourceMappingURL=TagsBulkAssignAsyncState.js.map