define('ember-cli-mirage/orm/associations/belongs-to', ['exports', 'ember-cli-mirage/orm/associations/association', 'lodash/assign', 'ember-cli-mirage/utils/inflector', 'ember-cli-mirage/utils/normalize-name', 'ember-cli-mirage/assert'], function (exports, _association, _assign2, _inflector, _normalizeName, _assert) {
  '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;
  };

  function _defineProperty(obj, key, value) {
    if (key in obj) {
      Object.defineProperty(obj, key, {
        value: value,
        enumerable: true,
        configurable: true,
        writable: true
      });
    } else {
      obj[key] = value;
    }

    return obj;
  }

  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 _possibleConstructorReturn(self, call) {
    if (!self) {
      throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
    }

    return call && (typeof call === "object" || typeof call === "function") ? call : self;
  }

  function _inherits(subClass, superClass) {
    if (typeof superClass !== "function" && superClass !== null) {
      throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
    }

    subClass.prototype = Object.create(superClass && superClass.prototype, {
      constructor: {
        value: subClass,
        enumerable: false,
        writable: true,
        configurable: true
      }
    });
    if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
  }

  var BelongsTo = function (_Association) {
    _inherits(BelongsTo, _Association);

    function BelongsTo() {
      _classCallCheck(this, BelongsTo);

      return _possibleConstructorReturn(this, (BelongsTo.__proto__ || Object.getPrototypeOf(BelongsTo)).apply(this, arguments));
    }

    _createClass(BelongsTo, [{
      key: 'getForeignKeyArray',
      value: function getForeignKeyArray() {
        return [(0, _inflector.camelize)(this.ownerModelName), this.getForeignKey()];
      }
    }, {
      key: 'getForeignKey',
      value: function getForeignKey() {
        return (0, _inflector.camelize)(this.key) + 'Id';
      }
    }, {
      key: 'addMethodsToModelClass',
      value: function addMethodsToModelClass(ModelClass, key) {
        var modelPrototype = ModelClass.prototype;
        var association = this;
        var foreignKey = this.getForeignKey();
        var associationHash = _defineProperty({}, key, this);

        modelPrototype.belongsToAssociations = (0, _assign2.default)(modelPrototype.belongsToAssociations, associationHash);

        // Add to target's dependent associations array
        this.schema.addDependentAssociation(this, this.modelName);

        // TODO: look how this is used. Are these necessary, seems like they could be gotten from the above?
        // Or we could use a single data structure to store this information?
        modelPrototype.associationKeys.push(key);
        modelPrototype.associationIdKeys.push(foreignKey);

        Object.defineProperty(modelPrototype, foreignKey, {
          get: function get() {
            this._tempAssociations = this._tempAssociations || {};
            var tempParent = this._tempAssociations[key];
            var id = void 0;

            if (tempParent === null) {
              id = null;
            } else {

              if (association.isPolymorphic) {
                if (tempParent) {
                  id = { id: tempParent.id, type: tempParent.modelName };
                } else {
                  id = this.attrs[foreignKey];
                }
              } else {
                if (tempParent) {
                  id = tempParent.id;
                } else {
                  id = this.attrs[foreignKey];
                }
              }
            }

            return id;
          },
          set: function set(id) {
            var tempParent = void 0;

            if (id === null) {
              tempParent = null;
            } else if (id !== undefined) {
              if (association.isPolymorphic) {
                (0, _assert.default)((typeof id === 'undefined' ? 'undefined' : _typeof(id)) === 'object', 'You\'re setting an ID on the polymorphic association \'' + association.key + '\' but you didn\'t pass in an object. Polymorphic IDs need to be in the form { type, id }.');
                tempParent = association.schema[(0, _normalizeName.toCollectionName)(id.type)].find(id.id);
              } else {
                tempParent = association.schema[(0, _normalizeName.toCollectionName)(association.modelName)].find(id);
                (0, _assert.default)(tempParent, 'Couldn\'t find ' + association.modelName + ' with id = ' + id);
              }
            }

            this[key] = tempParent;
          }
        });

        Object.defineProperty(modelPrototype, key, {
          get: function get() {
            this._tempAssociations = this._tempAssociations || {};

            var tempParent = this._tempAssociations[key];
            var foreignKeyId = this[foreignKey];
            var model = null;

            if (tempParent) {
              model = tempParent;
            } else if (foreignKeyId !== null) {
              if (association.isPolymorphic) {
                model = association.schema[(0, _normalizeName.toCollectionName)(foreignKeyId.type)].find(foreignKeyId.id);
              } else {
                model = association.schema[(0, _normalizeName.toCollectionName)(association.modelName)].find(foreignKeyId);
              }
            }

            return model;
          },
          set: function set(model) {
            this._tempAssociations = this._tempAssociations || {};
            this._tempAssociations[key] = model;

            if (model && model.hasInverseFor(association)) {
              var inverse = model.inverseFor(association);

              model.associate(this, inverse);
            }
          }
        });

        /*
          object.newParent
            - creates a new unsaved associated parent
           TODO: document polymorphic
        */
        modelPrototype['new' + (0, _inflector.capitalize)(key)] = function () {
          var modelName = void 0,
              attrs = void 0;

          if (association.isPolymorphic) {
            modelName = arguments.length <= 0 ? undefined : arguments[0];
            attrs = arguments.length <= 1 ? undefined : arguments[1];
          } else {
            modelName = association.modelName;
            attrs = arguments.length <= 0 ? undefined : arguments[0];
          }

          var parent = association.schema[(0, _normalizeName.toCollectionName)(modelName)].new(attrs);

          this[key] = parent;

          return parent;
        };

        /*
          object.createParent
            - creates a new saved associated parent, and immediately persists both models
           TODO: document polymorphic
        */
        modelPrototype['create' + (0, _inflector.capitalize)(key)] = function () {
          var modelName = void 0,
              attrs = void 0;
          if (association.isPolymorphic) {
            modelName = arguments.length <= 0 ? undefined : arguments[0];
            attrs = arguments.length <= 1 ? undefined : arguments[1];
          } else {
            modelName = association.modelName;
            attrs = arguments.length <= 0 ? undefined : arguments[0];
          }

          var parent = association.schema[(0, _normalizeName.toCollectionName)(modelName)].create(attrs);

          this[key] = parent;
          this.save();

          return parent.reload();
        };
      }
    }, {
      key: 'disassociateAllDependentsFromTarget',
      value: function disassociateAllDependentsFromTarget(model) {
        var _this2 = this;

        var owner = this.ownerModelName;
        var fk = void 0;

        if (this.isPolymorphic) {
          fk = { type: model.modelName, id: model.id };
        } else {
          fk = model.id;
        }

        var dependents = this.schema[(0, _normalizeName.toCollectionName)(owner)].where(function (potentialOwner) {
          var id = potentialOwner[_this2.getForeignKey()];

          if (!id) {
            return false;
          }

          if ((typeof id === 'undefined' ? 'undefined' : _typeof(id)) === 'object') {
            return id.type === fk.type && id.id === fk.id;
          } else {
            return id === fk;
          }
        });

        dependents.models.forEach(function (dependent) {
          dependent.disassociate(model, _this2);
          dependent.save();
        });
      }
    }]);

    return BelongsTo;
  }(_association.default);

  exports.default = BelongsTo;
});