"use strict";

var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard")["default"];

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault")["default"];

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports["default"] = exports.EXPANDED_KEY = void 0;

var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));

var _objectSpread3 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));

var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));

var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));

var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));

var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));

var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));

var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));

var _tslib = require("tslib");

var _mobx = require("mobx");

var _raf = _interopRequireDefault(require("raf"));

var _merge = _interopRequireDefault(require("lodash/merge"));

var _isObject = _interopRequireDefault(require("lodash/isObject"));

var _pick = _interopRequireDefault(require("lodash/pick"));

var _isNil = _interopRequireDefault(require("lodash/isNil"));

var _isString = _interopRequireDefault(require("lodash/isString"));

var _isNumber = _interopRequireDefault(require("lodash/isNumber"));

var _omit = _interopRequireDefault(require("lodash/omit"));

var _isPlainObject = _interopRequireDefault(require("lodash/isPlainObject"));

var _utils = require("../utils");

var _DataSet = _interopRequireWildcard(require("./DataSet"));

var _Field = _interopRequireDefault(require("./Field"));

var _utils2 = require("./utils");

var ObjectChainValue = _interopRequireWildcard(require("../object-chain-value"));

var _enum = require("./enum");

var _treeHelper = require("../tree-helper");

var _iteratorHelper = require("../iterator-helper");

/**
 * 记录ID生成器
 */
var IDGen = /*#__PURE__*/_regenerator["default"].mark(function _callee(start) {
  return _regenerator["default"].wrap(function _callee$(_context) {
    while (1) {
      switch (_context.prev = _context.next) {
        case 0:
          if (!true) {
            _context.next = 5;
            break;
          }

          _context.next = 3;
          return ++start;

        case 3:
          _context.next = 0;
          break;

        case 5:
        case "end":
          return _context.stop();
      }
    }
  }, _callee);
})(1000);

var EXPANDED_KEY = '__EXPANDED_KEY__'; // TODO:Symbol

exports.EXPANDED_KEY = EXPANDED_KEY;
var SELECTABLE_KEY = '__SELECTABLE_KEY__'; // TODO:Symbol

var DISABLED_KEY = '__DISABLED_KEY__'; // TODO:Symbol

var SELECT_KEY = '__SELECT_KEY__'; // TODO:Symbol

var UNSELECT_KEY = '__UNSELECT_KEY__'; // TODO:Symbol

var SELECT_TIMESTAMP = '__TIMESTAMP__'; // TODO:Symbol

function initRecordField(record, name, fieldProps) {
  var dataSet = record.dataSet;
  return (0, _utils2.processIntlField)(name, function (langProps) {
    return new _Field["default"](langProps, dataSet, record);
  }, fieldProps, dataSet);
}

function initRecordData(initData, dataSet) {
  var childrenField = dataSet.props.childrenField;
  return _mobx.observable.object(initData, childrenField && initData[childrenField] ? (0, _defineProperty2["default"])({}, childrenField, _mobx.observable.ref) : undefined);
}

var Record = /*#__PURE__*/function () {
  function Record() {
    var _this = this;

    var data = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
    var dataSet = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : new _DataSet["default"]();
    var status = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : _enum.RecordStatus.add;
    (0, _classCallCheck2["default"])(this, Record);
    (0, _mobx.runInAction)(function () {
      _this.dataSet = dataSet;
      _this.ownerFields = _mobx.observable.map();
      _this.status = status;
      _this.id = IDGen.next().value;
      var initData = (0, _mobx.isObservableObject)(data) ? (0, _mobx.toJS)(data) : data;
      _this.data = initRecordData(initData, dataSet);

      _this.processData(initData);

      (0, _raf["default"])(function () {
        dataSet.fields.forEach(function (field) {
          return field.processForLookupAndLovConfig(_this);
        });
      });
    });
  }

  (0, _createClass2["default"])(Record, [{
    key: "fields",
    get: function get() {
      var _this2 = this;

      (0, _utils.warning)(false, 'If you only want to get some property from dataSet field or calculated by `dynamicProps` or `computedProps`. Don\'t to iterate fields from `record.fields`, please use `dataSet.fields` instead. And then use `dsField.get(someProp, record)` to get the property which you needed.');
      var fields = new Map();
      this.dataSet.fields.forEach(function (_, name) {
        var tempField = _this2.getField(name);

        if (tempField) {
          fields.set(name, tempField);
        }
      });
      return _mobx.observable.map(fields);
    }
  }, {
    key: "pristineData",
    get: function get() {
      var dirtyData = this.dirtyData;
      var data = (0, _mobx.toJS)(this.data);

      if (dirtyData) {
        dirtyData.forEach(function (value, key) {
          return ObjectChainValue.set(data, key, value);
        });
      }

      return data;
    },
    set: function set(data) {
      var _this3 = this;

      (0, _mobx.runInAction)(function () {
        var dirtyData = _this3.dirtyData,
            dataSet = _this3.dataSet;

        if (dirtyData) {
          var newData = {};

          if (dirtyData.size) {
            dirtyData.forEach(function (_, key) {
              var item = ObjectChainValue.get(_this3.data, key);
              ObjectChainValue.set(newData, key, item);
              var newItem = ObjectChainValue.get(data, key);

              if ((0, _utils.isSame)(item, newItem)) {
                dirtyData["delete"](key);
              } else {
                dirtyData.set(key, newItem);
              }
            });
          }

          _this3.data = initRecordData((0, _merge["default"])({}, data, newData), dataSet);
        } else {
          _this3.data = initRecordData(data, dataSet);
        }
      });
    }
  }, {
    key: "selectedTimestamp",
    get: function get() {
      return this.getState(SELECT_TIMESTAMP);
    },
    set: function set(timestamp) {
      this.setState(SELECT_TIMESTAMP, timestamp);
    }
  }, {
    key: "selectable",
    get: function get() {
      var $selectable = this.getState(SELECTABLE_KEY);

      if ($selectable !== undefined) {
        return $selectable;
      }

      return (0, _utils2.getRecordDynamicProps)(this, 'selectable', true);
    },
    set: function set(selectable) {
      this.setState(SELECTABLE_KEY, selectable);
    }
  }, {
    key: "disabled",
    get: function get() {
      var $disabled = this.getState(DISABLED_KEY);

      if ($disabled !== undefined) {
        return $disabled;
      }

      return (0, _utils2.getRecordDynamicProps)(this, 'disabled', false);
    },
    set: function set(selectable) {
      this.setState(DISABLED_KEY, selectable);
    }
  }, {
    key: "isDataSetInAllPageSelection",
    get: function get() {
      return this.dataSet.isAllPageSelection;
    }
  }, {
    key: "isSelected",
    get: function get() {
      if (this.isDataSetInAllPageSelection) {
        return !this.getState(UNSELECT_KEY);
      }

      var $isSelected = this.getState(SELECT_KEY);

      if ($isSelected !== undefined) {
        return $isSelected;
      }

      return (0, _utils2.getRecordDynamicProps)(this, 'defaultSelected', false);
    },
    set: function set(isSelected) {
      if (isSelected !== this.isSelected) {
        var newState = (0, _defineProperty2["default"])({}, SELECT_TIMESTAMP, isSelected ? Date.now() : undefined);

        if (this.isDataSetInAllPageSelection) {
          newState[UNSELECT_KEY] = !isSelected;
        } else {
          newState[SELECT_KEY] = isSelected;
        }

        this.setState(newState);
      }
    }
  }, {
    key: "key",
    get: function get() {
      if (!this.isNew) {
        var primaryKey = this.dataSet.props.primaryKey;

        if (primaryKey) {
          var key = this.get(primaryKey);

          if ((0, _isString["default"])(key) || (0, _isNumber["default"])(key)) {
            return key;
          }
        }
      }

      return this.id;
    }
  }, {
    key: "index",
    get: function get() {
      return this.dataSet.indexOf(this);
    }
  }, {
    key: "indexInParent",
    get: function get() {
      var parent = this.parent;

      if (parent && parent.children) {
        return parent.children.indexOf(this);
      }

      return this.dataSet.treeRecords.indexOf(this);
    }
  }, {
    key: "isRemoved",
    get: function get() {
      return this.status === _enum.RecordStatus["delete"];
    }
  }, {
    key: "isNew",
    get: function get() {
      return this.status === _enum.RecordStatus.add;
    }
  }, {
    key: "isSelectionIndeterminate",
    get: function get() {
      if (this.dataSet.selection === _enum.DataSetSelection.multiple) {
        var children = this.children;

        if (children) {
          var checkedLength = 0;
          return children.some(function (record) {
            if (record.isSelectionIndeterminate) {
              return true;
            }

            if (record.isSelected) {
              checkedLength += 1;
            }

            return false;
          }) || checkedLength > 0 && checkedLength !== children.length;
        }
      }

      return false;
    }
  }, {
    key: "isIndeterminate",
    get: function get() {
      var dataSet = this.dataSet;
      var checkField = dataSet.props.checkField;

      if (checkField) {
        var field = dataSet.getField(checkField);
        var trueValue = field ? field.get(_enum.BooleanValue.trueValue, this) : true;
        var children = this.children;

        if (children) {
          var checkedLength = 0;
          return children.some(function (record) {
            if (record.isIndeterminate) {
              return true;
            }

            if (record.get(checkField) === trueValue) {
              checkedLength += 1;
            }

            return false;
          }) || checkedLength > 0 && checkedLength !== children.length;
        }
      }

      return false;
    }
  }, {
    key: "isExpanded",
    get: function get() {
      var dataSet = this.dataSet;
      var expandField = dataSet.props.expandField;

      if (expandField) {
        var expanded = this.get(expandField);
        var field = dataSet.getField(expandField);
        return expanded === (field ? field.get(_enum.BooleanValue.trueValue, this) : true);
      }

      var $expanded = this.getState(EXPANDED_KEY);

      if ($expanded !== undefined) {
        return $expanded;
      }

      return (0, _utils2.getRecordDynamicProps)(this, 'defaultExpanded', false);
    },
    set: function set(expand) {
      var dataSet = this.dataSet;
      var expandField = dataSet.props.expandField;

      if (expandField) {
        var field = dataSet.getField(expandField);
        this.set(expandField, field ? field.get(expand ? _enum.BooleanValue.trueValue : _enum.BooleanValue.falseValue, this) : expand);
      } else {
        this.setState(EXPANDED_KEY, expand);
      }
    }
  }, {
    key: "previousRecord",
    get: function get() {
      var parent = this.parent;
      var children = parent ? parent.children : this.dataSet.treeData;

      if (children) {
        return children[children.indexOf(this) - 1];
      }

      return undefined;
    }
  }, {
    key: "nextRecord",
    get: function get() {
      var parent = this.parent;
      var children = parent ? parent.children : this.dataSet.treeData;

      if (children) {
        return children[children.indexOf(this) + 1];
      }

      return undefined;
    }
  }, {
    key: "records",
    get: function get() {
      var dataSet = this.dataSet;
      var cascadeParent = this.cascadeParent;

      if (cascadeParent && !cascadeParent.isCurrent) {
        return cascadeParent.getCascadeRecordsIncludeDelete(dataSet.parentName) || [];
      }

      return dataSet.records;
    }
  }, {
    key: "parents",
    get: function get() {
      var parent = this.parent;

      if (parent) {
        return [parent].concat((0, _toConsumableArray2["default"])(parent.parents));
      }

      return [];
    }
  }, {
    key: "path",
    get: function get() {
      var path = [this].concat((0, _toConsumableArray2["default"])(this.parents));
      path.reverse();
      return path;
    }
  }, {
    key: "level",
    get: function get() {
      var parent = this.parent;

      if (parent) {
        return parent.level + 1;
      }

      return 0;
    }
  }, {
    key: "dirty",
    get: function get() {
      var _this4 = this;

      var status = this.status;

      if (status === _enum.RecordStatus.update) {
        return true;
      }

      var dirtyData = this.dirtyData;

      if (dirtyData && dirtyData.size > 0) {
        return true;
      }

      return Object.keys(this.dataSet.children).some(function (key) {
        return (_this4.getCascadeRecordsIncludeDelete(key) || []).some(_utils2.isDirtyRecord);
      });
    }
  }, {
    key: "cascadeParent",
    get: function get() {
      var _this5 = this;

      var _this$dataSet = this.dataSet,
          parent = _this$dataSet.parent,
          parentName = _this$dataSet.parentName;

      if (parent && parentName) {
        return parent.cascadeRecords.find(function (record) {
          return (record.getCascadeRecordsIncludeDelete(parentName) || []).indexOf(_this5) !== -1;
        });
      }

      return undefined;
    }
  }, {
    key: "processTreeLevel",
    value: function processTreeLevel(props) {
      var dataSet = props.dataSet,
          value = props.value,
          fieldName = props.fieldName;
      var _dataSet$props = dataSet.props,
          parentField = _dataSet$props.parentField,
          idField = _dataSet$props.idField,
          childrenField = _dataSet$props.childrenField;

      if (!childrenField && parentField && idField) {
        if (fieldName === parentField) {
          var parent = this.parent;

          if (parent) {
            var oldChildren = parent.children;

            if (oldChildren) {
              var oldIndex = oldChildren.indexOf(this);

              if (oldIndex !== -1) {
                oldChildren.splice(oldIndex, 1);
              }

              if (!oldChildren.length) {
                parent.children = undefined;
              }
            }
          }

          var newParent = dataSet.find(function (r) {
            return r.get(idField) === value;
          });
          this.parent = newParent;

          if (newParent) {
            var children = newParent.children;

            if (children) {
              children.push(this);

              if (children.length > 1) {
                var orderFields = (0, _utils2.getOrderFields)(dataSet);

                if (orderFields.length > 0) {
                  newParent.children = (0, _utils2.sortTree)(children, orderFields);
                }
              }
            } else {
              newParent.children = [this];
            }
          }
        }
      }
    }
    /**
     * 转换成普通数据
     * 一般用于父级联数据源中的json类型字段
     * 禁止通过此方法获取某一个或几个字段值
     */

  }, {
    key: "toData",
    value: function toData(needIgnore, noCascade, isCascadeSelect) {
      var _this6 = this;

      var all = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;

      if (_mobx._isComputingDerivation && (0, _mobx._isComputingDerivation)()) {
        (0, _utils.warning)(false, 'Please do not use the `record.toData` method to get the value during the rendering phase, please use `record.get` instead.');
      }

      var status = this.status,
          dataSet = this.dataSet;
      var dataToJSON = dataSet.dataToJSON,
          fields = dataSet.fields;
      var cascade = noCascade === undefined && dataToJSON ? (0, _utils2.useCascade)(dataToJSON) : !noCascade;
      var normal = all || dataToJSON && (0, _utils2.useNormal)(dataToJSON);
      var dirty = status !== _enum.RecordStatus.sync;
      var childrenKeys = cascade ? Object.keys(dataSet.children) : undefined;
      var jsonFieldKeys = childrenKeys && (0, _iteratorHelper.iteratorReduce)(fields.entries(), function (fieldKeys, _ref2) {
        var _ref3 = (0, _slicedToArray2["default"])(_ref2, 2),
            key = _ref3[0],
            field = _ref3[1];

        if (field.get('type', _this6) === _enum.FieldType.json && childrenKeys.some(function (childKey) {
          return key === childKey || childKey.startsWith("".concat(key, "."));
        })) {
          fieldKeys.push(key);
        }

        return fieldKeys;
      }, []);
      var json = this.normalizeData(needIgnore, jsonFieldKeys);

      if (cascade && this.normalizeCascadeData(json, normal, isCascadeSelect)) {
        dirty = true;
      }

      if (jsonFieldKeys) {
        jsonFieldKeys.forEach(function (key) {
          return ObjectChainValue.set(json, key, JSON.stringify(ObjectChainValue.get(json, key)), fields, _this6);
        });
      }

      return (0, _objectSpread3["default"])((0, _objectSpread3["default"])({}, json), {}, {
        __dirty: dirty
      });
    }
    /**
     * 转换成用于提交的数据
     */

  }, {
    key: "toJSONData",
    value: function toJSONData(noCascade, isCascadeSelect) {
      var status = this.status,
          dataSet = this.dataSet;
      return (0, _objectSpread3["default"])((0, _objectSpread3["default"])({}, this.toData(true, noCascade, isCascadeSelect, false)), {}, (0, _defineProperty2["default"])({
        __id: this.id
      }, dataSet.getConfig('statusKey'), dataSet.getConfig('status')[status === _enum.RecordStatus.sync ? _enum.RecordStatus.update : status]));
    }
  }, {
    key: "validate",
    value: function validate(all, noCascade) {
      var _this7 = this;

      var dataSet = this.dataSet;
      this.validating = true;
      var promises = [];

      if (all || this.status !== _enum.RecordStatus.sync) {
        dataSet.fields.forEach(function (field) {
          return promises.push(field.checkValidity(_this7));
        });
      }

      if (!noCascade) {
        var children = dataSet.children;
        var childrenKeys = Object.keys(children);

        if (childrenKeys.length) {
          var dataSetSnapshot = this.dataSetSnapshot,
              isCurrent = this.isCurrent;
          childrenKeys.forEach(function (key) {
            var snapshot = dataSetSnapshot && dataSetSnapshot[key];
            var ds = children[key];
            var child = isCurrent ? ds : snapshot && new _DataSet["default"](undefined, dataSet.context).restore(snapshot);

            if (child) {
              promises.push(child.validate());
            } else {
              var dataToJSON = ds.dataToJSON;
              var cascade = noCascade === undefined && dataToJSON ? (0, _utils2.useCascade)(dataToJSON) : !noCascade;
              (((0, _utils2.useSelected)(dataToJSON) ? _this7.getCascadeSelectedRecords(key) : _this7.getCascadeRecords(key)) || []).forEach(function (record) {
                return promises.push(record.validate(false, !cascade));
              });
            }
          });
        }
      }

      return Promise.all(promises).then(function (results) {
        var valid = results.every(function (result) {
          return result;
        });

        if (!dataSet.validating) {
          dataSet.reportValidity({
            record: _this7,
            errors: _this7.getValidationErrors(),
            valid: valid
          });
        }

        delete _this7.validating;
        return valid;
      })["catch"](function (error) {
        delete _this7.validating;
        throw error;
      });
    }
  }, {
    key: "cancelReportValidity",
    value: function cancelReportValidity() {
      var prepareForReport = this.prepareForReport;

      if (prepareForReport && prepareForReport.timeout) {
        window.clearTimeout(prepareForReport.timeout);
      }
    }
  }, {
    key: "reportValidity",
    value: function reportValidity(result, fromField) {
      var _this8 = this;

      var dataSet = this.dataSet;

      if (!dataSet.validating) {
        var prepareForReport = (0, _utils2.getIf)(this, 'prepareForReport', {
          result: [],
          valid: true
        });

        if (!result.valid) {
          prepareForReport.valid = false;
          prepareForReport.result.push(result);
        }

        if (prepareForReport.timeout) {
          window.clearTimeout(prepareForReport.timeout);
        }

        prepareForReport.timeout = window.setTimeout(function () {
          dataSet.reportValidity({
            record: _this8,
            errors: prepareForReport.result,
            valid: prepareForReport.valid
          }, fromField);
          delete _this8.prepareForReport;
        }, 200);
      }
    }
  }, {
    key: "getValidationErrors",
    value: function getValidationErrors() {
      var _this9 = this;

      var validationErrors = this.validationErrors;
      var results = [];

      if (validationErrors) {
        validationErrors.forEach(function (errors, fieldName) {
          var field = _this9.ownerFields.get(fieldName) || _this9.dataSet.getField(fieldName);

          if (field && errors.length) {
            results.push({
              field: field,
              errors: errors,
              valid: false
            });
          }
        });
      }

      return results;
    }
  }, {
    key: "addField",
    value: function addField(name, fieldProps) {
      var dataSet = this.dataSet,
          ownerFields = this.ownerFields;

      if (!dataSet.getField(name)) {
        dataSet.addField(name, fieldProps);
      }

      var oldField = ownerFields.get(name);

      if (oldField) {
        return oldField.replace(fieldProps);
      }

      var _initRecordField = initRecordField(this, name, fieldProps),
          _initRecordField2 = (0, _slicedToArray2["default"])(_initRecordField, 2),
          field = _initRecordField2[0],
          intlFields = _initRecordField2[1];

      ownerFields.set(name, field);

      if (intlFields) {
        ownerFields.merge(intlFields);
      }

      return field;
    }
  }, {
    key: "getField",
    value: function getField(fieldName) {
      if (fieldName) {
        (0, _utils.warning)(false, 'If you only want to get some property from dataSet field or calculated by `dynamicProps` or `computedProps`. Don\'t to get field from `record.getField`, please use `dataSet.getField` instead. And then use `dsField.get(someProp, record)` to get the property which you needed.');
        {
          var _field = this.ownerFields.get(fieldName);

          if (_field) {
            return _field;
          }
        }
        var tempFields = (0, _utils2.getIf)(this, 'tempFields', function () {
          return new Map();
        });
        {
          var _field2 = tempFields.get(fieldName);

          if (_field2) {
            return _field2;
          }
        }
        var field = new _Field["default"]({
          name: fieldName
        }, this.dataSet, this);
        tempFields.set(fieldName, field);
        return field;
      }
    }
  }, {
    key: "getCascadeRecordsIncludeDelete",
    value: function getCascadeRecordsIncludeDelete(fieldName) {
      if (fieldName) {
        var childDataSet = this.dataSet.children[fieldName];

        if (childDataSet) {
          if (this.isCurrent) {
            return childDataSet.records.slice();
          }

          var dataSetSnapshot = this.dataSetSnapshot;
          var snapshot = dataSetSnapshot && dataSetSnapshot[fieldName];

          if (snapshot) {
            return snapshot.records;
          }

          var cascadeRecordsMap = (0, _utils2.getIf)(this, 'cascadeRecordsMap', {});
          var cascadeRecords = cascadeRecordsMap[fieldName];

          if (cascadeRecords) {
            return cascadeRecords;
          }

          var data = this.get(fieldName);
          var cascading = (0, _utils2.getIf)(this, 'cascading', {});

          if (!cascading[fieldName] && (0, _mobx.isObservableArray)(data)) {
            cascading[fieldName] = true;
            var records = childDataSet.processData(data, this.isNew ? _enum.RecordStatus.add : _enum.RecordStatus.sync);
            delete cascading[fieldName];
            cascadeRecordsMap[fieldName] = records;
            return records;
          }
        }
      }
    }
  }, {
    key: "getCascadeRecords",
    value: function getCascadeRecords(fieldName) {
      var records = this.getCascadeRecordsIncludeDelete(fieldName);

      if (records) {
        return records.filter(function (r) {
          return !r.isRemoved;
        });
      }
    }
  }, {
    key: "getCascadeSelectedRecordsIncludeDelete",
    value: function getCascadeSelectedRecordsIncludeDelete(fieldName) {
      var records = this.getCascadeRecordsIncludeDelete(fieldName);

      if (records) {
        return records.filter(function (r) {
          return r.isSelected;
        });
      }
    }
  }, {
    key: "getCascadeSelectedRecords",
    value: function getCascadeSelectedRecords(fieldName) {
      var records = this.getCascadeRecordsIncludeDelete(fieldName);

      if (records) {
        return records.filter(function (r) {
          return !r.isRemoved && r.isSelected;
        });
      }
    }
  }, {
    key: "get",
    value: function get(fieldName) {
      return (0, _utils2.getRecordValue)(this, function (child, checkField) {
        return child.get(checkField);
      }, fieldName);
    }
  }, {
    key: "set",
    value: function set(item, value) {
      var _this10 = this;

      if ((0, _isString["default"])(item)) {
        var dataSet = this.dataSet;
        var oldName = item;
        var fieldName = (0, _utils2.getChainFieldName)(this, oldName);
        var field = dataSet.getField(oldName) || dataSet.getField(fieldName) || (0, _utils2.findBindField)(oldName, fieldName, this) || (0, _DataSet.addDataSetField)(dataSet, oldName);
        (0, _utils2.checkFieldType)(value, field, this);
        var oldValue = (0, _mobx.toJS)(this.get(fieldName));
        var newValue = (0, _utils2.processValue)(value, field, this);
        var newValueForCompare = (0, _utils2.processToJSON)(newValue, field, this);
        var fields = dataSet.fields;

        if (!(0, _utils.isSame)((0, _utils2.processToJSON)(oldValue, field, this), newValueForCompare)) {
          ObjectChainValue.set(this.data, fieldName, newValue, fields, this);
          var dirtyData = (0, _utils2.getIf)(this, 'dirtyData', function () {
            return _mobx.observable.map();
          });

          if (!dirtyData.has(fieldName)) {
            dirtyData.set(fieldName, oldValue);

            if (this.status === _enum.RecordStatus.sync) {
              this.status = _enum.RecordStatus.update;

              if (this.isCached && dataSet.cacheModifiedKeys) {
                dataSet.cachedModified.push(this);
              }
            }
          } else if ((0, _utils.isSame)((0, _utils2.processToJSON)(dirtyData.get(fieldName), field, this), newValueForCompare)) {
            dirtyData["delete"](fieldName);

            if (this.status === _enum.RecordStatus.update && dirtyData.size === 0) {
              this.status = _enum.RecordStatus.sync;

              if (this.isCached) {
                if (!dataSet.cacheSelectionKeys || !this.isSelected) {
                  this.isCached = false;
                }

                var cachedModified = dataSet.cachedModified;
                var cachedIndex = cachedModified.indexOf(this);

                if (cachedIndex > -1) {
                  cachedModified.splice(cachedIndex, 1);
                }
              }
            }
          }

          dataSet.fireEvent(_enum.DataSetEvents.update, {
            dataSet: dataSet,
            record: this,
            name: oldName,
            value: newValue,
            oldValue: oldValue
          });
          var _dataSet$props2 = dataSet.props,
              checkField = _dataSet$props2.checkField,
              treeCheckStrictly = _dataSet$props2.treeCheckStrictly;

          if (treeCheckStrictly !== true && checkField && fieldName === (0, _utils2.getChainFieldName)(this, checkField)) {
            var children = this.children;

            if (children) {
              children.forEach(function (record) {
                return record.set(fieldName, value);
              });
            }
          }

          this.processTreeLevel({
            dataSet: dataSet,
            value: newValue,
            fieldName: oldName
          });
        }

        [field].concat((0, _toConsumableArray2["default"])((0, _utils2.findBindFields)(field, fields, true, this)), (0, _toConsumableArray2["default"])((0, _utils2.findBindTargetFields)(field, fields, true, this)), (0, _toConsumableArray2["default"])((0, _utils2.findMinOrMaxFields)(field, fields, this))).forEach(function (oneField) {
          return oneField.checkValidity(_this10);
        });
      } else if ((0, _isPlainObject["default"])(item)) {
        Object.keys(item).forEach(function (key) {
          return _this10.set(key, item[key]);
        });
      }

      return this;
    }
  }, {
    key: "getPristineValue",
    value: function getPristineValue(fieldName) {
      if (fieldName) {
        var chainFieldName = (0, _utils2.getChainFieldName)(this, fieldName);
        var dirtyData = this.dirtyData;

        if (dirtyData) {
          if (dirtyData.has(chainFieldName)) {
            return dirtyData.get(chainFieldName);
          }

          var v;
          var has = (0, _iteratorHelper.iteratorSome)(dirtyData.entries(), function (_ref4) {
            var _ref5 = (0, _slicedToArray2["default"])(_ref4, 2),
                key = _ref5[0],
                value = _ref5[1];

            if (chainFieldName.startsWith("".concat(key, "."))) {
              v = ObjectChainValue.get(value, chainFieldName.replace("".concat(key, "."), ''));
              return true;
            }

            return false;
          });

          if (has) {
            return v;
          }
        }

        return this.get(chainFieldName);
      }
    }
  }, {
    key: "init",
    value: function init(item, value) {
      var _this11 = this;

      var data = this.data,
          dirtyData = this.dirtyData;

      if ((0, _isString["default"])(item)) {
        var dataSet = this.dataSet;
        var oldName = item;
        var fieldName = (0, _utils2.getChainFieldName)(this, oldName);
        var field = dataSet.getField(oldName) || dataSet.getField(fieldName) || (0, _utils2.findBindField)(oldName, fieldName, this) || (0, _DataSet.addDataSetField)(dataSet, fieldName);
        var newValue = (0, _utils2.processValue)(value, field, this);

        if (dirtyData) {
          dirtyData["delete"](fieldName);
        }

        ObjectChainValue.set(data, fieldName, newValue, dataSet.fields, this);
        field.commit(this);
        this.processTreeLevel({
          dataSet: dataSet,
          value: newValue,
          fieldName: oldName
        });
      } else if ((0, _isPlainObject["default"])(item)) {
        Object.keys(item).forEach(function (key) {
          return _this11.init(key, item[key]);
        });
      }

      return this;
    }
  }, {
    key: "clone",
    value: function clone() {
      var dataSet = this.dataSet;
      var cloneData = this.toData();
      var primaryKey = dataSet.props.primaryKey;

      if (primaryKey) {
        delete cloneData[primaryKey];
      }

      return new Record(cloneData, dataSet);
    }
  }, {
    key: "ready",
    value: function ready() {
      return Promise.resolve(true); // return Promise.all([...this.fields.values()].map(field => field.ready()));
    }
  }, {
    key: "tls",
    value: function () {
      var _tls = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee2(name) {
        var _this12 = this;

        var dataSet, tlsKey, tlsData, axios, lang, primaryKey, newConfig, result, dataKey;
        return _regenerator["default"].wrap(function _callee2$(_context2) {
          while (1) {
            switch (_context2.prev = _context2.next) {
              case 0:
                dataSet = this.dataSet;
                tlsKey = dataSet.getConfig('tlsKey');

                if (!name) {
                  _context2.next = 16;
                  break;
                }

                tlsData = this.get(tlsKey) || {};

                if (name in tlsData) {
                  _context2.next = 16;
                  break;
                }

                axios = dataSet.axios, lang = dataSet.lang;
                primaryKey = dataSet.props.primaryKey;
                newConfig = (0, _utils2.axiosConfigAdapter)('tls', dataSet, {}, primaryKey && {
                  key: this.get(primaryKey)
                }, {
                  name: name,
                  record: this
                });

                if (!(newConfig.url && !this.isNew)) {
                  _context2.next = 15;
                  break;
                }

                _context2.next = 11;
                return axios(newConfig);

              case 11:
                result = _context2.sent;

                if (result) {
                  dataKey = dataSet.getConfig('dataKey');
                  this.commitTls((0, _utils2.generateResponseData)(result, dataKey)[0], name);
                }

                _context2.next = 16;
                break;

              case 15:
                this.commitTls((0, _iteratorHelper.iteratorReduce)(dataSet.fields.entries(), function (data, _ref6) {
                  var _ref7 = (0, _slicedToArray2["default"])(_ref6, 2),
                      key = _ref7[0],
                      field = _ref7[1];

                  if (field.get('type', _this12) === _enum.FieldType.intl) {
                    data[key] = (0, _defineProperty2["default"])({}, lang, _this12.get(key));
                  }

                  return data;
                }, {}), name);

              case 16:
              case "end":
                return _context2.stop();
            }
          }
        }, _callee2, this);
      }));

      function tls(_x) {
        return _tls.apply(this, arguments);
      }

      return tls;
    }()
  }, {
    key: "reset",
    value: function reset() {
      var _this13 = this;

      this.cancelReportValidity();
      var status = this.status,
          dataSet = this.dataSet,
          dirty = this.dirty,
          isRemoved = this.isRemoved,
          validationErrors = this.validationErrors;
      var hasError = false;

      if (validationErrors && validationErrors.size > 0) {
        hasError = true;
        validationErrors.clear();
      }

      dataSet.fields.forEach(function (field) {
        return field.commit(_this13);
      });

      if (status === _enum.RecordStatus.update || isRemoved) {
        this.status = _enum.RecordStatus.sync;
      }

      if (hasError || isRemoved || dirty) {
        this.data = initRecordData((0, _mobx.toJS)(this.pristineData), dataSet);
        this.dirtyData = undefined;
        this.memo = undefined;

        if (!dataSet.resetInBatch) {
          dataSet.fireEvent(_enum.DataSetEvents.reset, {
            records: [this],
            dataSet: dataSet,
            record: this
          });
        }
      }

      return this;
    }
  }, {
    key: "save",
    value: function save() {
      this.memo = (0, _mobx.toJS)(this.data);
      return this;
    }
  }, {
    key: "restore",
    value: function restore() {
      var memo = this.memo;

      if (memo) {
        this.set(memo);
        this.memo = undefined;
      }

      return this;
    }
  }, {
    key: "clear",
    value: function clear() {
      var _this14 = this;

      this.dataSet.fields.forEach(function (_, key) {
        return _this14.set(key, null);
      });
      return this;
    }
  }, {
    key: "commit",
    value: function commit(data, dataSet) {
      var _this15 = this;

      if (dataSet) {
        var records = this.records;

        if (this.isRemoved) {
          {
            var index = records.indexOf(this);

            if (index !== -1) {
              if (dataSet.records === records) {
                dataSet.totalCount -= 1;
              }

              records.splice(index, 1);
            }
          }
          var parent = this.parent;

          if (parent) {
            var children = parent.children;

            if (children) {
              var _index = children.indexOf(this);

              if (_index !== -1) {
                children.splice(_index, 1);
              }

              if (!children.length) {
                parent.children = undefined;
              }
            }

            this.parent = undefined;
          }

          return this;
        }

        if (this.isNew) {
          var _index2 = records.indexOf(this);

          if (_index2 !== -1 && dataSet.records === records) {
            dataSet.totalCount += 1;
          }
        }

        if (data) {
          this.data = initRecordData(data, dataSet);
          this.processData(data, true);
          var _children = dataSet.children;
          var keys = Object.keys(_children);

          if (keys.length) {
            var isCurrent = this.isCurrent;
            var tmpDs = new _DataSet["default"](undefined, dataSet.context);
            var dataSetSnapshot = (0, _utils2.getIf)(this, 'dataSetSnapshot', {});
            keys.forEach(function (key) {
              var snapshot = dataSetSnapshot[key];
              var ds = _children[key];
              var child = isCurrent ? ds : snapshot && tmpDs.restore(snapshot);

              if (child) {
                dataSetSnapshot[key] = child.commitData(data[key] || []).snapshot();
              } else {
                var cascadeRecords = _this15.getCascadeRecordsIncludeDelete(key);

                if (cascadeRecords) {
                  cascadeRecords.forEach(function (r) {
                    return r.commit((0, _omit["default"])(r.toData(), ['__dirty']), ds);
                  });
                }
              }
            });
          }
        }

        dataSet.fields.forEach(function (field) {
          return field.commit(_this15);
        });
      }

      this.dirtyData = undefined;
      this.status = _enum.RecordStatus.sync;
      return this;
    }
  }, {
    key: "setState",
    value: function setState(item, value) {
      var state = (0, _utils2.getIf)(this, 'state', function () {
        return _mobx.observable.map();
      });

      if ((0, _isString["default"])(item)) {
        state.set(item, value);
      } else if ((0, _isPlainObject["default"])(item)) {
        state.merge(item);
      }

      return this;
    }
  }, {
    key: "getState",
    value: function getState(key) {
      var state = this.state;
      return state && state.get(key);
    }
  }, {
    key: "treeReduce",
    value: function treeReduce(fn, initialValue) {
      return (0, _treeHelper.treeReduce)([this], fn, initialValue);
    }
  }, {
    key: "commitTls",
    value: function commitTls() {
      var _this16 = this;

      var data = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
      var name = arguments.length > 1 ? arguments[1] : undefined;
      var dataSet = this.dataSet;
      var tlsKey = dataSet.getConfig('tlsKey');

      if (!(name in data)) {
        data[name] = {};
      }

      Object.keys(data).forEach(function (key) {
        var value = data[key];
        var field = dataSet.getField(key);

        if (field) {
          var transformResponse = field.get('transformResponse', _this16);

          if (transformResponse) {
            var originValue = (0, _objectSpread3["default"])({}, value);
            Object.keys(value).forEach(function (language) {
              value[language] = transformResponse(value[language], originValue);
            });
          }
        }

        ObjectChainValue.set(_this16.data, key, value[dataSet.lang]);
        ObjectChainValue.set(_this16.data, "".concat(tlsKey, ".").concat(key), value);
      });
    }
  }, {
    key: "processFieldValue",
    value: function processFieldValue(fieldName, field, fields, newData, data, needMerge) {
      var value = ObjectChainValue.get(newData, fieldName);
      var chainFieldName = (0, _utils2.getChainFieldName)(this, fieldName);
      var transformResponse = field.get('transformResponse', this);

      if (chainFieldName !== fieldName) {
        var bindValue = ObjectChainValue.get(newData, chainFieldName);

        if ((0, _isNil["default"])(value) && !(0, _isNil["default"])(bindValue)) {
          value = bindValue;
        }
      }

      if (transformResponse) {
        value = transformResponse(value, data);
      }

      value = (0, _utils2.processValue)(value, field, this, !needMerge && this.isNew);

      if (value === null) {
        value = undefined;
      }

      if (needMerge && (0, _isObject["default"])(value)) {
        var oldValue = ObjectChainValue.get(this.data, chainFieldName);

        if ((0, _isObject["default"])(oldValue)) {
          value = (0, _merge["default"])(oldValue, value);
        }
      }

      ObjectChainValue.set(newData, chainFieldName, value, fields, this);
      ObjectChainValue.set(this.data, chainFieldName, value, fields, this);
    }
  }, {
    key: "setValidationError",
    value: function setValidationError(name, result) {
      var validationErrors = (0, _utils2.getIf)(this, 'validationErrors', function () {
        return _mobx.observable.map();
      });
      var originalResult = validationErrors.get(name);

      if (result && result.length || originalResult && originalResult.length) {
        validationErrors.set(name, result);
      }
    }
  }, {
    key: "getValidationError",
    value: function getValidationError(name) {
      var validationErrors = this.validationErrors;

      if (validationErrors) {
        return validationErrors.get(name);
      }
    }
  }, {
    key: "clearValidationError",
    value: function clearValidationError(name) {
      var _this17 = this;

      var validationErrors = this.validationErrors;

      if (validationErrors) {
        var errors = validationErrors.get(name);

        if (errors) {
          errors.some(function (error) {
            if (error.ruleName === 'uniqueError') {
              var validationProps = error.validationProps;

              if (validationProps) {
                var unique = validationProps.unique;

                if ((0, _isString["default"])(unique)) {
                  _this17.dataSet.fields.forEach(function (field, fieldName) {
                    if (fieldName !== name && field.get('unique', _this17) === unique && !field.get('multiple', _this17) && !field.get('range', _this17)) {
                      _this17.clearValidationError(fieldName);
                    }
                  });
                }
              }

              return true;
            }

            return false;
          });
        }

        return validationErrors["delete"](name);
      }
    }
  }, {
    key: "processData",
    value: function processData() {
      var _this18 = this;

      var data = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
      var needMerge = arguments.length > 1 ? arguments[1] : undefined;
      var newData = (0, _objectSpread3["default"])({}, data);
      var fields = (0, _utils2.getSortedFields)(this.dataSet);
      fields.forEach(function (field, fieldName) {
        return _this18.processFieldValue(fieldName, field, fields, newData, data, needMerge);
      });
    }
  }, {
    key: "normalizeData",
    value: function normalizeData(needIgnore, jsonFields) {
      var _this19 = this;

      var dataSet = this.dataSet;
      var fields = dataSet.fields,
          dataToJSON = dataSet.dataToJSON;
      var onlyDirtyField = needIgnore && dataToJSON ? (0, _utils2.useDirtyField)(dataToJSON) : false;
      var neverKeys = onlyDirtyField ? (0, _utils2.getUniqueKeysAndPrimaryKey)(dataSet) : [];
      var json = onlyDirtyField ? (0, _pick["default"])(this.data, neverKeys) : (0, _mobx.toJS)(this.data);
      var fieldIgnore = onlyDirtyField ? _enum.FieldIgnore.clean : undefined;
      var objectFieldsList = [];
      var normalFields = [];
      var ignoreFieldNames = new Set();
      fields.forEach(function (field, key) {
        if (field && (!jsonFields || !jsonFields.includes(key))) {
          var ignore = field.get('ignore', _this19) || fieldIgnore;

          if (needIgnore && !neverKeys.includes(key) && (ignore === _enum.FieldIgnore.always || ignore === _enum.FieldIgnore.clean && !field.isDirty(_this19))) {
            ignoreFieldNames.add(key);
          } else {
            var type = field.get('type', _this19);

            if (type === _enum.FieldType.object) {
              var level = key.split('.').length - 1;
              objectFieldsList[level] = (objectFieldsList[level] || []).concat(field);
            } else {
              normalFields.push(field);
            }
          }
        }
      });
      [].concat(objectFieldsList, [normalFields]).forEach(function (items) {
        if (items) {
          items.forEach(function (field) {
            var name = field.name;
            var value = ObjectChainValue.get(onlyDirtyField ? (0, _objectSpread3["default"])((0, _objectSpread3["default"])({}, _this19.data), json) : json, name);
            var bind = field.get('bind', _this19);
            var transformRequest = field.get('transformRequest', _this19);

            if (bind) {
              value = _this19.get((0, _utils2.getChainFieldName)(_this19, name));
            }

            var old = value;
            value = (0, _utils2.processToJSON)(value, field, _this19);

            if (transformRequest) {
              // compatible old logic
              value = (0, _isString["default"])(field.get('multiple', _this19)) && (0, _mobx.isArrayLike)(old) ? transformRequest(value, _this19) : (0, _utils2.processToJSON)(transformRequest(old, _this19), field, _this19);
            }

            if (value !== undefined) {
              ObjectChainValue.set(json, name, value, fields, _this19);
            } else {
              ignoreFieldNames.add(name);
            }
          });
        }
      });
      (0, _toConsumableArray2["default"])(ignoreFieldNames).forEach(function (key) {
        return ObjectChainValue.remove(json, key);
      });
      return json;
    }
  }, {
    key: "normalizeCascadeData",
    value: function normalizeCascadeData(json, normal, isSelect) {
      var _this20 = this;

      var dataSetSnapshot = this.dataSetSnapshot,
          dataSet = this.dataSet,
          isRemoved = this.isRemoved;
      var dirty = false;
      var children = dataSet.children,
          fields = dataSet.fields;

      if (isRemoved) {
        (0, _utils2.childrenInfoForDelete)(json, children);
      } else {
        var keys = Object.keys(children);

        if (keys.length) {
          var isCurrent = this.isCurrent;
          keys.forEach(function (name) {
            var snapshot = dataSetSnapshot && dataSetSnapshot[name];
            var child = !isCurrent && snapshot && new _DataSet["default"](undefined, dataSet.context).restore(snapshot) || children[name];

            if (child) {
              var dataToJSON = child.dataToJSON;

              var records = _this20.getCascadeRecordsIncludeDelete(name);

              var selected = isSelect || (0, _utils2.useSelected)(dataToJSON) ? _this20.getCascadeSelectedRecordsIncludeDelete(name) : records;
              var jsonArray = normal || (0, _utils2.useNormal)(dataToJSON) ? records && (0, _utils2.generateData)(records) : selected && (0, _utils2.generateJSONData)(child, selected);

              if (jsonArray) {
                if (jsonArray.dirty) {
                  dirty = true;
                }

                ObjectChainValue.set(json, name, jsonArray.data, fields, _this20);
              }
            }
          });
        }
      }

      return dirty;
    }
  }]);
  return Record;
}();

exports["default"] = Record;
(0, _tslib.__decorate)([_mobx.computed], Record.prototype, "fields", null);
(0, _tslib.__decorate)([_mobx.observable], Record.prototype, "ownerFields", void 0);
(0, _tslib.__decorate)([_mobx.observable], Record.prototype, "data", void 0);
(0, _tslib.__decorate)([_mobx.observable], Record.prototype, "dirtyData", void 0);
(0, _tslib.__decorate)([_mobx.observable], Record.prototype, "validationErrors", void 0);
(0, _tslib.__decorate)([_mobx.observable], Record.prototype, "lookupTokens", void 0);
(0, _tslib.__decorate)([_mobx.observable], Record.prototype, "attachmentCaches", void 0);
(0, _tslib.__decorate)([_mobx.computed], Record.prototype, "pristineData", null);
(0, _tslib.__decorate)([_mobx.observable], Record.prototype, "status", void 0);
(0, _tslib.__decorate)([_mobx.computed], Record.prototype, "isSelected", null);
(0, _tslib.__decorate)([_mobx.observable], Record.prototype, "isCurrent", void 0);
(0, _tslib.__decorate)([_mobx.observable], Record.prototype, "isCached", void 0);
(0, _tslib.__decorate)([_mobx.observable], Record.prototype, "editing", void 0);
(0, _tslib.__decorate)([_mobx.observable], Record.prototype, "pending", void 0);
(0, _tslib.__decorate)([_mobx.observable], Record.prototype, "childrenLoaded", void 0);
(0, _tslib.__decorate)([_mobx.observable], Record.prototype, "state", void 0);
(0, _tslib.__decorate)([_mobx.computed], Record.prototype, "key", null);
(0, _tslib.__decorate)([_mobx.computed], Record.prototype, "index", null);
(0, _tslib.__decorate)([_mobx.computed], Record.prototype, "indexInParent", null);
(0, _tslib.__decorate)([_mobx.computed], Record.prototype, "isSelectionIndeterminate", null);
(0, _tslib.__decorate)([_mobx.computed], Record.prototype, "isIndeterminate", null);
(0, _tslib.__decorate)([_mobx.computed], Record.prototype, "isExpanded", null);
(0, _tslib.__decorate)([_mobx.computed], Record.prototype, "previousRecord", null);
(0, _tslib.__decorate)([_mobx.computed], Record.prototype, "nextRecord", null);
(0, _tslib.__decorate)([_mobx.computed], Record.prototype, "records", null);
(0, _tslib.__decorate)([_mobx.observable], Record.prototype, "children", void 0);
(0, _tslib.__decorate)([_mobx.observable], Record.prototype, "parent", void 0);
(0, _tslib.__decorate)([_mobx.computed], Record.prototype, "parents", null);
(0, _tslib.__decorate)([_mobx.computed], Record.prototype, "path", null);
(0, _tslib.__decorate)([_mobx.computed], Record.prototype, "dirty", null);
(0, _tslib.__decorate)([_mobx.computed], Record.prototype, "cascadeParent", null);
(0, _tslib.__decorate)([_mobx.action], Record.prototype, "processTreeLevel", null);
(0, _tslib.__decorate)([_mobx.action], Record.prototype, "addField", null);
(0, _tslib.__decorate)([_mobx.action], Record.prototype, "set", null);
(0, _tslib.__decorate)([_mobx.action], Record.prototype, "init", null);
(0, _tslib.__decorate)([_mobx.action], Record.prototype, "tls", null);
(0, _tslib.__decorate)([_mobx.action], Record.prototype, "reset", null);
(0, _tslib.__decorate)([_mobx.action], Record.prototype, "save", null);
(0, _tslib.__decorate)([_mobx.action], Record.prototype, "restore", null);
(0, _tslib.__decorate)([_mobx.action], Record.prototype, "clear", null);
(0, _tslib.__decorate)([_mobx.action], Record.prototype, "commit", null);
(0, _tslib.__decorate)([_mobx.action], Record.prototype, "setState", null);
(0, _tslib.__decorate)([_mobx.action], Record.prototype, "commitTls", null);
(0, _tslib.__decorate)([_mobx.action], Record.prototype, "setValidationError", null);
(0, _tslib.__decorate)([_mobx.action], Record.prototype, "clearValidationError", null);
//# sourceMappingURL=Record.js.map
