import Store from './store';
import Source from './source';
import OCMemorySource from 'orbit_common/memory_source';

var get = Ember.get,
    set = Ember.set;

var Context = Source.extend({
  store: null,
  SourceClass: OCMemorySource,

  schema: null,
  idField: Ember.computed.alias('schema.idField'),

  init: function() {
    var store = get(this, 'store');
    Ember.assert("`Context.store` must be initialized with an instance of a `Store`", store);

    var schema = get(store, 'schema');
    set(this, 'schema', schema);

    this.typeMaps = {};

    this._super.apply(this, arguments);

    this.then = this._source.transformQueue.then;
    this._source.on('didTransform', this.didTransform, this);
  },

  willDestroy: function() {
    this._super.apply(this, arguments);
    this._source.off('didTransform', this.didTransform, this);
  },

  typeMapFor: function(type) {
    var typeMap = this.typeMaps[type];

    if (typeMap) return typeMap;

    typeMap = {
      records: {},
      type: type
    };

    this.typeMaps[type] = typeMap;

    return typeMap;
  },

  transform: function(operation) {
    return this._source.transform(operation);
  },

  didTransform: function(operation, inverse) {
    console.log('didTransform', operation, inverse);
    var _this = this,
        op = operation.op,
        path = operation.path,
        value = operation.value;

    if (op === 'replace') {
      console.log('replace', path[0], path[1], path[2], value);
      var record = _this._lookupRecord(path[0], path[1]);
      var prop = path[2];
      record.propertyDidChange(prop);
    }

    // TODO - other ops
  },

  add: function(type, properties) {
    var _this = this;

    // TODO: normalize properties
    return this._source.add(type, properties).then(function(data) {
      var id = data[_this.get('idField')];
      return _this._lookupRecord(type, id);
    });
  },

  remove: function(type, id) {
    var _this = this;

    return this._source.remove(type, id).then(function() {
      _this._unloadRecord(type, id);
    });
  },

  find: function(type, id) {
    var _this = this;

    return this._source.find(type, id).then(function(data) {

      if (id === undefined || Ember.typeOf(id) === 'object') {
        return _this._lookupRecordsFromData(type, data);

      } else if (Ember.isArray(id)) {
        return _this._lookupRecords(type, id);

      } else {
        return _this._lookupRecord(type, id);
      }
    });
  },

  recordForId: function(type, id) {
    return this.typeMapFor(type).records[id];
  },

  getAttribute: function(record, key) {
    var id = record[get(this, 'idField')],
        path = [record.constructor.typeKey, id, key];

    return this._source.retrieve(path);
  },

  setAttribute: function(record, key, value) {
    var id = record[get(this, 'idField')];
    return this._source.patch(record.constructor.typeKey, id, key, value);
  },

  _lookupRecord: function(type, id) {
    var typeMap = this.typeMapFor(type),
        record = typeMap.records[id];

    if (record === undefined) {
      var model = get(this, 'store').modelFor(type);

      var data = {
        context: this
      };
      data[get(this, 'idField')] = id;

      record = model._create(data);

      typeMap.records[id] = record;
    }

    return record;
  },

  _lookupRecords: function(type, ids) {
    var _this = this;
    return ids.map(function(id) {
      return _this._lookupRecord(type, id);
    });
  },

  _lookupRecordsFromData: function(type, data) {
    var idField = this.get('idField');
    var ids = data.map(function(recordData) {
      return recordData[idField];
    });
    return this._lookupRecords(type, ids);
  },

  _unloadRecord: function(type, id) {
    var typeMap = this.typeMapFor(type),
        record = typeMap.records[id];

    if (record) {
      delete typeMap.records[id];
      record.destroy();
    }
  }
});

export default Context;
@@ -740,48 +740,8 @@
 ) %7B%0A
-    this._super.apply(this, arguments);%0A
     
@@ -791,32 +791,72 @@
 ansform, this);%0A
+    this._super.apply(this, arguments);%0A
   %7D,%0A%0A  typeMapF

reorder calls in `willDestroy`