// These are statuses for in-flight requests. If a request has no status
// associated with it, then it would have a status of `NULL`.
export const xhrStatuses = {
  PENDING: 'PENDING',
  SUCCEEDED: 'SUCCEEDED',
  FAILED: 'FAILED',
  ABORTED: 'ABORTED',
  NULL: 'NULL'
};

// Updates a single resource's metadata
export function updateResourceMeta({resourceMeta, newMeta, id, replace}) {
  const existingMeta = replace ? {} : resourceMeta[id];
  return {
    // Shallow clone the current resourceMeta
    ...resourceMeta,
    // Update the key that is the "id" of the resource
    [id]: {
      // Shallow clone the existing metadata for this resource
      ...existingMeta,
      // Shallow clone the passed-in metadata
      ...newMeta
    }
  };
}

// Similar to `updateResourceMeta`, but it accepts an array of IDs instead of
// a single ID. Used for bulk updating meta.
export function updateManyResourceMetas({resourceMeta, newMeta, ids, replace}) {
  const next = replace ? {} : {...resourceMeta};

  ids.forEach((id) => {
    const current = next[id];
    next[id] = {
      ...current,
      ...newMeta
    };
  });

  return next;
}

// Insert a new resource or update an existing resource.
export function upsertResource({resources, resource, id, idAttribute, replace}) {
  // Attempt to find the resource by its ID. If the ID doesn't exist, or if
  // no resource by that ID exists, then we append it to the end as a new
  // resource.
  const resourceIndex = id && resources.findIndex(item => item[idAttribute] === id);
  if (!id || resourceIndex === -1) {
    return [...resources, resource];
  }

  const shallowClone = [...resources];

  let resourceToInsert;
  if (!replace) {
    const currentResource = shallowClone[resourceIndex];
    resourceToInsert = {
      ...currentResource,
      ...resource
    };
  } else {
    resourceToInsert = resource;
  }

  // Otherwise, it does exist and we add it to the list at the appropriate
  // location
  shallowClone.splice(resourceIndex, 1, resourceToInsert);
  return shallowClone;
}

// Similar to `upsertResource`, but for many resources.
export function upsertManyResources({resources, newResources, idAttribute, replace}) {
  const shallowClone = replace ? [] : [...resources];

  newResources.forEach(resource => {
    const id = resource[idAttribute];
    const resourceIndex = id && resources.findIndex(item => item[idAttribute] === id);

    if (!id || resourceIndex === -1) {
      return shallowClone.push(resource);
    }

    let resourceToInsert;
    if (!replace) {
      const currentResource = shallowClone[resourceIndex];
      resourceToInsert = {
        ...currentResource,
        ...resource
      };
    } else {
      resourceToInsert = resource;
    }

    shallowClone.splice(resourceIndex, 1, resourceToInsert);
  });

  return shallowClone;
}

export const initialResourceMetaState = {
  // The status of any existing request to update this resource
  updatingStatus: xhrStatuses.NULL,
  // The status of any existing request to fetch this resource
  retrievingStatus: xhrStatuses.NULL,
  // The status of an any existing request to delete this resource. Note that
  // this will never be "SUCCEEDED," as a successful delete removes the
  // resource from the store.
  deletingStatus: xhrStatuses.NULL
};

export function snakeCase(str) {
  return str
    .replace(/([a-z])([A-Z])/g, '$1_$2')
    .replace(/\b([A-Z]+)([A-Z])([a-z])/, '$1_$2$3')
    .toLowerCase();
}

export function generateDefaultInitialState() {
  return {
    // These are the actual resources that the server sends back.
    resources: [],
    // This is metadata about _specific_ resources. For instance, if a DELETE
    // is in flight for a book with ID 24, then you could find that here.
    resourceMeta: {},
    // This is metadata about the entire collection of resources. For instance,
    // on page load, you might fetch all of the resources. The XHR status for
    // that request would live here.
    resourceListMeta: {
      retrievingStatus: xhrStatuses.NULL,
      creatingStatus: xhrStatuses.NULL
    }
  };
}

@@ -1526,16 +1526,78 @@
 == id);%0A
+  const shallowClone = Array.prototype.slice.call(resources);%0A
   if (!i
@@ -1633,38 +1633,34 @@
     
-return %5B...resources, 
+shallowClone.push(
 resource
 %5D;%0A 
@@ -1659,23 +1659,21 @@
 urce
-%5D
+)
 ;%0A  
-%7D%0A%0A  const
+  return
  sha
@@ -1685,26 +1685,13 @@
 lone
- = %5B...resources%5D;
+;%0A  %7D
 %0A%0A  
@@ -2271,12 +2271,35 @@
 %5D : 
-%5B...
+Array.prototype.slice.call(
 reso
@@ -2303,17 +2303,17 @@
 esources
-%5D
+)
 ;%0A%0A  new

Remove use of spread