"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
exports.__esModule = true;
exports.SchemaFieldsState = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _bexCore = require("@wix/bex-core");
var _mobx = require("mobx");
var _indexOfCompareFn = require("../indexOfCompareFn");
const STORAGE_KEY = 'schema-card-layout';
class SchemaFieldsState {
  constructor(params) {
    (0, _defineProperty2.default)(this, "_storedFields", []);
    (0, _defineProperty2.default)(this, "initTask", new _bexCore.TaskState());
    (0, _defineProperty2.default)(this, "_persistQueue", Promise.resolve());
    (0, _defineProperty2.default)(this, "params", void 0);
    this.params = params;
    (0, _mobx.makeObservable)(this, {
      _storedFields: _mobx.observable,
      orderedFields: _mobx.computed,
      setFieldVisibility: _mobx.action.bound,
      setFieldOrder: _mobx.action.bound
    });
  }
  init() {
    this.initTask.runOnce(async () => {
      try {
        await this._fetchFromStorage();
      } catch (e) {
        console.error(e);
      }
    });
  }
  get orderedFields() {
    if (!this._storedFields.length) {
      return this.params.fields;
    }
    // Fields not in storage all get index -1; stable sort preserves their declaration order
    return [...this.params.fields].sort((0, _indexOfCompareFn.indexOfCompareFn)(this._storedFields, f => f == null ? void 0 : f.id));
  }
  isFieldVisible(id) {
    const field = this.params.fields.find(f => f.id === id);
    if (!field) {
      return true;
    } // unknown id — render by default
    if (field.hideable === false) {
      return true;
    } // non-hideable — always visible
    const stored = this._storedFields.find(f => f.id === id);
    return stored ? stored.isVisible ?? true : field.isVisible ?? true;
  }
  setFieldVisibility(id, isVisible) {
    const idx = this._storedFields.findIndex(f => f.id === id);
    if (idx >= 0) {
      // Replace element (not mutate in-place) so MobX tracks the array change
      this._storedFields[idx] = {
        ...this._storedFields[idx],
        isVisible
      };
    } else {
      this._storedFields.push({
        id,
        isVisible
      });
    }
    // Wait for init to complete before persisting — prevents overwriting the
    // full stored layout when called before _fetchFromStorage resolves.
    // Serialize writes: chain onto the queue so rapid toggles don't race.
    this._persistQueue = this._persistQueue.then(() => this.initTask.status.promise).then(() => this.persistFields()).catch(e => console.error(e));
  }
  setFieldOrder(orderedFields) {
    const storedMap = new Map(this._storedFields.map(f => [f.id, f]));
    const declaredMap = new Map(this.params.fields.map(f => [f.id, f]));

    // Rebuild _storedFields in the new order, preserving existing visibility.
    // Only include fields that are still declared; unknown ids are silently dropped.
    this._storedFields = orderedFields.filter(f => declaredMap.has(f.id)).map(f => storedMap.get(f.id) ?? {
      id: f.id,
      isVisible: declaredMap.get(f.id).isVisible ?? true
    });
    this._persistQueue = this._persistQueue.then(() => this.initTask.status.promise).then(() => this.persistFields()).catch(e => console.error(e));
  }
  async persistFields() {
    const fields = this._storedFields.map(({
      id,
      isVisible
    }) => ({
      id,
      isVisible
    }));
    await this.params.dataCapsule.setItem(STORAGE_KEY, {
      fields
    });
  }
  async _fetchFromStorage() {
    const {
      dataCapsule,
      fields
    } = this.params;
    let storedLayout = null;
    try {
      const raw = await dataCapsule.getItem(STORAGE_KEY);
      storedLayout = raw && typeof raw === 'object' && Array.isArray(raw.fields) ? raw : null;
    } catch (e) {
      if (e instanceof Error && e.message === 'Key was not found in capsule') {
        storedLayout = null;
      } else {
        throw e;
      }
    }
    if (!storedLayout) {
      return;
    }

    // Merge: keep stored order/visibility; append new fields; drop removed ones.
    // Dedup by id — keeps the first occurrence, discarding any corrupt duplicates.
    const declaredIds = new Set(fields.map(f => f.id));
    const seenIds = new Set();
    const merged = storedLayout.fields.filter(f => {
      if (!(f != null && f.id) || !declaredIds.has(f.id) || seenIds.has(f.id)) {
        return false;
      }
      seenIds.add(f.id);
      return true;
    });
    fields.forEach(f => {
      if (!merged.some(s => s.id === f.id)) {
        merged.push({
          id: f.id,
          isVisible: f.isVisible ?? true
        });
      }
    });
    (0, _mobx.runInAction)(() => {
      this._storedFields = merged;
    });
  }
}
exports.SchemaFieldsState = SchemaFieldsState;
//# sourceMappingURL=SchemaFieldsState.js.map