define('ember-cli-mirage/db-collection', ['exports', 'lodash/assign', 'lodash/map', 'lodash/isEqual', 'lodash/sortBy'], function (exports, _assign2, _map2, _isEqual2, _sortBy2) {
  'use strict';

  Object.defineProperty(exports, "__esModule", {
    value: true
  });

  var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
    return typeof obj;
  } : function (obj) {
    return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
  };

  var _slicedToArray = function () {
    function sliceIterator(arr, i) {
      var _arr = [];
      var _n = true;
      var _d = false;
      var _e = undefined;

      try {
        for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
          _arr.push(_s.value);

          if (i && _arr.length === i) break;
        }
      } catch (err) {
        _d = true;
        _e = err;
      } finally {
        try {
          if (!_n && _i["return"]) _i["return"]();
        } finally {
          if (_d) throw _e;
        }
      }

      return _arr;
    }

    return function (arr, i) {
      if (Array.isArray(arr)) {
        return arr;
      } else if (Symbol.iterator in Object(arr)) {
        return sliceIterator(arr, i);
      } else {
        throw new TypeError("Invalid attempt to destructure non-iterable instance");
      }
    };
  }();

  function _classCallCheck(instance, Constructor) {
    if (!(instance instanceof Constructor)) {
      throw new TypeError("Cannot call a class as a function");
    }
  }

  var _createClass = function () {
    function defineProperties(target, props) {
      for (var i = 0; i < props.length; i++) {
        var descriptor = props[i];
        descriptor.enumerable = descriptor.enumerable || false;
        descriptor.configurable = true;
        if ("value" in descriptor) descriptor.writable = true;
        Object.defineProperty(target, descriptor.key, descriptor);
      }
    }

    return function (Constructor, protoProps, staticProps) {
      if (protoProps) defineProperties(Constructor.prototype, protoProps);
      if (staticProps) defineProperties(Constructor, staticProps);
      return Constructor;
    };
  }();

  function duplicate(data) {
    if (Array.isArray(data)) {
      return data.map(duplicate);
    } else {
      return (0, _assign2.default)({}, data);
    }
  }

  /**
   *  A collection of db records i.e. a database table.
   *  @class DbCollection
   *  @constructor
   *  @public
   */

  var DbCollection = function () {
    function DbCollection(name, initialData, IdentityManager) {
      _classCallCheck(this, DbCollection);

      this.name = name;
      this._records = [];
      this.identityManager = new IdentityManager();

      if (initialData) {
        this.insert(initialData);
      }
    }

    /**
     * Returns a copy of the data, to prevent inadvertent data manipulation.
     * @method all
     * @public
     */


    _createClass(DbCollection, [{
      key: 'all',
      value: function all() {
        return duplicate(this._records);
      }
    }, {
      key: 'insert',
      value: function insert(data) {
        var _this = this;

        if (!Array.isArray(data)) {
          return this._insertRecord(data);
        } else {
          // Need to sort in order to ensure IDs inserted in the correct order
          var sorted = (0, _sortBy2.default)(data, 'id');
          return (0, _map2.default)(sorted, function (x) {
            return _this._insertRecord(x);
          });
        }
      }
    }, {
      key: 'find',
      value: function find(ids) {
        if (Array.isArray(ids)) {
          var records = this._findRecords(ids).filter(Boolean).map(duplicate); // Return a copy

          return records;
        } else {
          var record = this._findRecord(ids);
          if (!record) {
            return null;
          }

          // Return a copy
          return duplicate(record);
        }
      }
    }, {
      key: 'findBy',
      value: function findBy(query) {
        var record = this._findRecordBy(query);
        if (!record) {
          return null;
        }

        // Return a copy
        return duplicate(record);
      }
    }, {
      key: 'where',
      value: function where(query) {
        return this._findRecordsWhere(query).map(duplicate);
      }
    }, {
      key: 'firstOrCreate',
      value: function firstOrCreate(query) {
        var attributesForCreate = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};

        var queryResult = this.where(query);

        var _queryResult = _slicedToArray(queryResult, 1),
            record = _queryResult[0];

        if (record) {
          return record;
        } else {
          var mergedAttributes = (0, _assign2.default)(attributesForCreate, query);
          var createdRecord = this.insert(mergedAttributes);

          return createdRecord;
        }
      }
    }, {
      key: 'update',
      value: function update(target, attrs) {
        var _this2 = this;

        var records = void 0;

        if (typeof attrs === 'undefined') {
          attrs = target;
          var changedRecords = [];

          this._records.forEach(function (record) {
            var oldRecord = (0, _assign2.default)({}, record);

            _this2._updateRecord(record, attrs);

            if (!(0, _isEqual2.default)(oldRecord, record)) {
              changedRecords.push(record);
            }
          });

          return changedRecords;
        } else if (typeof target === 'number' || typeof target === 'string') {
          var id = target;
          var record = this._findRecord(id);

          this._updateRecord(record, attrs);

          return record;
        } else if (Array.isArray(target)) {
          var ids = target;
          records = this._findRecords(ids);

          records.forEach(function (record) {
            _this2._updateRecord(record, attrs);
          });

          return records;
        } else if ((typeof target === 'undefined' ? 'undefined' : _typeof(target)) === 'object') {
          var query = target;
          records = this._findRecordsWhere(query);

          records.forEach(function (record) {
            _this2._updateRecord(record, attrs);
          });

          return records;
        }
      }
    }, {
      key: 'remove',
      value: function remove(target) {
        var _this3 = this;

        var records = void 0;

        if (typeof target === 'undefined') {
          this._records = [];
          this.identityManager.reset();
        } else if (typeof target === 'number' || typeof target === 'string') {
          var record = this._findRecord(target);
          var index = this._records.indexOf(record);
          this._records.splice(index, 1);
        } else if (Array.isArray(target)) {
          records = this._findRecords(target);
          records.forEach(function (record) {
            var index = _this3._records.indexOf(record);
            _this3._records.splice(index, 1);
          });
        } else if ((typeof target === 'undefined' ? 'undefined' : _typeof(target)) === 'object') {
          records = this._findRecordsWhere(target);
          records.forEach(function (record) {
            var index = _this3._records.indexOf(record);
            _this3._records.splice(index, 1);
          });
        }
      }
    }, {
      key: '_findRecord',
      value: function _findRecord(id) {
        id = id.toString();

        var _records$filter = this._records.filter(function (obj) {
          return obj.id === id;
        }),
            _records$filter2 = _slicedToArray(_records$filter, 1),
            record = _records$filter2[0];

        return record;
      }
    }, {
      key: '_findRecordBy',
      value: function _findRecordBy(query) {
        return this._findRecordsWhere(query)[0];
      }
    }, {
      key: '_findRecords',
      value: function _findRecords(ids) {
        return ids.map(this._findRecord, this);
      }
    }, {
      key: '_findRecordsWhere',
      value: function _findRecordsWhere(query) {
        var records = this._records;

        function defaultQueryFunction(record) {
          var keys = Object.keys(query);

          return keys.every(function (key) {
            return String(record[key]) === String(query[key]);
          });
        }

        var queryFunction = (typeof query === 'undefined' ? 'undefined' : _typeof(query)) === 'object' ? defaultQueryFunction : query;

        return records.filter(queryFunction);
      }
    }, {
      key: '_insertRecord',
      value: function _insertRecord(data) {
        var attrs = duplicate(data);

        if (attrs && (attrs.id === undefined || attrs.id === null)) {
          attrs.id = this.identityManager.fetch(attrs);
        } else {
          attrs.id = attrs.id.toString();

          this.identityManager.set(attrs.id);
        }

        this._records.push(attrs);

        return duplicate(attrs);
      }
    }, {
      key: '_updateRecord',
      value: function _updateRecord(record, attrs) {
        var targetId = attrs && attrs.hasOwnProperty('id') ? attrs.id.toString() : null;
        var currentId = record.id;

        if (targetId && currentId !== targetId) {
          throw new Error('Updating the ID of a record is not permitted');
        }

        for (var attr in attrs) {
          if (attr === 'id') {
            continue;
          }

          record[attr] = attrs[attr];
        }
      }
    }]);

    return DbCollection;
  }();

  exports.default = DbCollection;
});