/** @flow */
/* global gapi */

var ActionType = require('./ActionType.js');
var API = require('./API.js');
var Dispatcher = require('./Dispatcher.js');
var MessageTranslator = require('./MessageTranslator');
var RSVP = require('rsvp');
var _ = require('lodash');

function getByID(
  options: {id: string}
): Promise<Object> {
  return API.wrap(() => {
    return API.execute(
      gapi.client.gmail.users.threads.get({userId: 'me', id: options.id})
    ).then(response => response.result);
  });
}

declare class ListResult {
  nextPageToken: ?string;
  resultSizeEstimate: number;
  items: Array<Object>;
}

function list(
  options: {maxResults: number; query: ?string; pageToken: ?string}
): Promise<ListResult> {
  return API.wrap(() => {
    return API.execute(gapi.client.gmail.users.threads.list({
      userId: 'me',
      maxResults: options.maxResults,
      q: options.query || null,
      pageToken: options.pageToken || null,
    })).then(listResponse => {
      var threadIDs = (listResponse.threads || []).map(m => m.id);

      if (!threadIDs.length) {
        return Promise.resolve({
          nextPageToken: null,
          resultSizeEstimate: 0,
          items: [],
        });
      }

      var batch = gapi.client.newHttpBatch();
      threadIDs.forEach(id => {
        batch.add(
          gapi.client.gmail.users.threads.get({userId: 'me', id}),
          {id}
        );
      });

      return API.execute(batch).then(batchResponse => {
        var allMessages = [];
        var threads = threadIDs.map(threadID => {
          var thread = batchResponse[threadID].result;
          var messages = thread.messages.map(MessageTranslator.translate);
          allMessages.push.apply(allMessages, messages);
          return {
            id: threadID,
            messageIDs: _.pluck(messages, 'id'),
          };
        });

        Dispatcher.dispatch({
          type: ActionType.Message.ADD_MANY,
          messages: allMessages,
        });

        return {
          nextPageToken: listResponse.nextPageToken,
          resultSizeEstimate: listResponse.resultSizeEstimate,
          items: threads,
        };
      });
    });
  });
}

function markAsRead(options: {threadID: String}) {
  return API.wrap(() =>
    API.execute(gapi.client.gmail.users.threads.modify({
      userId: 'me',
      id: options.threadID,
      removeLabelIds: ['UNREAD'],
    }))
  );
}

function archive(options: {threadID: String}) {
  return API.wrap(() =>
    API.execute(gapi.client.gmail.users.threads.modify({
      userId: 'me',
      id: options.threadID,
      removeLabelIds: ['INBOX'],
    }))
  );
}

function moveToInbox(options: {threadID: String}) {
  return API.wrap(() =>
    API.execute(gapi.client.gmail.users.threads.modify({
      userId: 'me',
      id: options.threadID,
      addLabelIds: ['INBOX'],
    }))
  );
}

function markAsUnread(options: {threadID: String}) {
  return API.wrap(() =>
    API.execute(gapi.client.gmail.users.threads.modify({
      userId: 'me',
      id: options.threadID,
      addLabelIds: ['UNREAD'],
    }))
  );
}

function unstar(options: {threadID: String}) {
  return API.wrap(() =>
    API.execute(gapi.client.gmail.users.threads.modify({
      userId: 'me',
      id: options.threadID,
      removeLabelIds: ['STARRED'],
    }))
  );
}

function star(options: {threadID: String}) {
  return API.wrap(() =>
    API.execute(gapi.client.gmail.users.threads.modify({
      userId: 'me',
      id: options.threadID,
      addLabelIds: ['STARRED'],
    }))
  );
}

module.exports = {
  archive,
  getByID,
  list,
  markAsRead,
  markAsUnread,
  moveToInbox,
  star,
  unstar,
};

@@ -468,16 +468,29 @@
 onse =%3E 
+_getThreads(%5B
 response
@@ -496,16 +496,21 @@
 e.result
+%5D)%5B0%5D
 );%0A  %7D);
@@ -1495,137 +1495,415 @@
 var 
-allMessages = %5B%5D;%0A        var threads = threadIDs.map(threadID =%3E %7B%0A          var thread = batchResponse%5Bt
+results = threadIDs.map(threadID =%3E batchResponse%5BthreadID%5D.result);%0A        var threads = _getThreads(results);%0A%0A        return %7B%0A          nextPageToken: listResponse.nextPageToken,%0A          resultSizeEstimate: listResponse.resultSizeEstimate,%0A          items: threads,%0A        %7D;%0A      %7D);%0A    %7D);%0A  %7D);%0A%7D%0A%0Afunction _getT
 hread
-ID%5D.
+s(
 result
-;%0A      
+s) %7B%0A  var allMessages = %5B%5D;%0A  var threads = results.map(thread =%3E %7B%0A
     
@@ -1967,22 +1967,16 @@
 slate);%0A
-      
     allM
@@ -2018,22 +2018,16 @@
 sages);%0A
-      
     retu
@@ -2037,22 +2037,16 @@
 %7B%0A      
-  
-    
 id: thre
@@ -2047,26 +2047,21 @@
 : thread
-ID,%0A      
+.id,%0A
       me
@@ -2103,36 +2103,18 @@
     
-      %7D;%0A      
+%7D;%0A
   %7D);%0A%0A
-      
   Di
@@ -2137,22 +2137,16 @@
 h(%7B%0A    
-   
-   
 type: Ac
@@ -2172,22 +2172,16 @@
 D_MANY,%0A
-      
     mess
@@ -2203,27 +2203,15 @@
 es,%0A
-      
   %7D);%0A%0A
-      
   re
@@ -2219,185 +2219,15 @@
 urn 
-%7B%0A          nextPageToken: listResponse.nextPageToken,%0A          resultSizeEstimate: listResponse.resultSizeEstimate,%0A          items: threads,%0A        %7D;%0A      %7D);%0A    %7D);%0A  %7D)
+threads
 ;%0A%7D%0A

Make ThreadAPI consistent about handling results