import DS from "ember-data";
import Ember from 'ember';
import EmbedExtractor from "./embed-extractor";

// requestType values that indicate that we are loading a collection, not
// a single resource
var findManyRequestTypes = ["findMany", "findAll", "findHasMany", "findQuery"];

// Reserved keys, per the HAL spec
var halReservedKeys = ['_embedded', '_links'];

var reservedKeys = halReservedKeys.concat(['meta']);

export default DS.ActiveModelSerializer.extend({
  serializeIntoHash: function(hash, type, record, options){
    var serialized = this.serialize(record, options);
    Ember.keys(serialized).forEach(function(key){
      hash[key] = serialized[key];
    });
  },

  /*
   pass `requestType` to extractMeta so we know if we are
   dealing with a list resource (i.e., GET /users) which will
   have meta data in the root of the payload, i.e.:
   {
     page: 1,
     total_pages: 5,
     _embedded: {
       users: [{...}, ...]
     }
   }

   If the requestType is for a single resource we cannot determine
   which properties are metadata and which are part of the payload
   for that resource because they are all at the root level of the payload,
   so punt on that here -- per-model serializers can override extractMeta
   if they need to.

   @return {Object} The payload, modified to remove metadata
  */
  extractMeta: function(store, type, payload, requestType){

    if ( findManyRequestTypes.indexOf(requestType) > -1 ) {

      var meta = {};
      Ember.keys(payload).forEach(function(key){
        if (reservedKeys.indexOf(key) > -1) { return; }

        meta[key] = payload[key];
        delete payload[key];
      });

      // set the metadata
      store.metaForType(type, meta);
    }

    this._super(store, type, payload);

    return payload;
  },

  /*
   * Override `extract` so we can pass the requestType to `extractMeta`
   */
  extract: function(store, type, payload, id, requestType) {
    payload = this.extractMeta(store, type, payload, requestType);

    var specificExtract = "extract" + requestType.charAt(0).toUpperCase() + requestType.substr(1);
    return this[specificExtract](store, type, payload, id, requestType);
  },

  extractSingle: function(store, primaryType, rawPayload, recordId) {
    var extracted = new EmbedExtractor(rawPayload).
      extractSingle(primaryType.typeKey);

    return this._super(store, primaryType, extracted, recordId);
  },

  extractArray: function(store, primaryType, rawPayload) {
    var extracted = new EmbedExtractor(rawPayload).extractArray();

    return this._super(store, primaryType, extracted);
  },

  normalizePayload: function(payload){
    // top-level _links (such as 'self') can be ignored
    if (payload._links) {
      delete payload._links;
    }
    return this._super(payload);
  },

  normalize: function(type, hash, property) {
    var links = hash._links || {};
    delete hash._links;

    hash.links = hash.links || {};
    delete hash.links.self;

    Ember.keys(links).forEach(function(link){
      if (link === 'self') { return; }

      // Do not include a link for a property that already
      // exists on the hash, because Ember-Data will fetch that
      // resource by the link instead of using the included data
      if (!hash[link]) {
        hash.links[link] = links[link].href;
      }
    });

    return this._super(type, hash, property);
  }

});

@@ -685,14 +685,11 @@
 %0A   
-pass %60
+%60__
 requ
@@ -701,28 +701,18 @@
 pe%60 
-to extractMeta so we
+is used to
  kno
@@ -780,20 +780,19 @@
 ) which 
-will
+may
 %0A   have
@@ -858,29 +858,84 @@
 : 1,
-%0A     total_pages: 5,
+                // %3C-- metadata%0A     total_pages: 5,         // %3C-- metadata
 %0A   
@@ -1396,34 +1396,64 @@
 e, type, payload
-, 
+)%7B%0A    var requestType = this.__
 requestType)%7B%0A%0A 
@@ -1447,18 +1447,17 @@
 uestType
-)%7B
+;
 %0A%0A    if
@@ -1891,12 +1891,13 @@
 can 
-pass
+store
  the
@@ -1913,12 +1913,12 @@
 ype 
-to %60
+for 
 extr
@@ -1924,17 +1924,16 @@
 ractMeta
-%60
 %0A   */%0A 
@@ -2000,203 +2000,90 @@
     
-payload = this.extractMeta(store, type, payload, requestType);%0A%0A    var specificExtract = %22extract%22 + requestType.charAt(0).toUpperCase() + requestType.substr(1);%0A    return this%5BspecificExtract%5D
+this.__requestType = requestType; // used by %60extractMeta%60%0A%0A    return this._super
 (sto

Use instance property to avoid changing method signature for extractMeta