'use strict';

var _                   = require('lodash');
var mongoose            = require('mongoose');
var AdministerCalendars = require('../services/AdministerCalendars');
var ChannelEntry        = mongoose.model('Channel', require('../data/schema/channel'));
const EventEmitter = require('events');
const Rx = require('rxjs');
const debug = require('debug')('eventController');

mongoose.Promise = require('bluebird');

class CalendarEmitter extends EventEmitter {}
const calendarEmitter = new CalendarEmitter();

let Interface = {
  load,
  emitEvents,
  // [ Event1, Event2 ] => Observable.of(Event1)-->Observable.of(Event2)
  observable: Rx.Observable.fromEvent(calendarEmitter, 'CALENDAR_UPDATE').flatMap(x => x).share(),
  _filterForLatestEvents,
  _parseUserIdFromEmail,
};

module.exports = Interface;

/**
 * Loading to the controller based on Channel Id
 * @param  {String} channelId Channel Id recieved from the notification
 * @return {Void} None
 */
function load(channelId) {
  debug('load %s', channelId);
  getChannelEntry(channelId).then(channelEntry => {
    debug('Found channel entry for %s: %O', channelId, channelEntry);
    // Old channel that may have existed due to overlap renewals
    if (!channelEntry) { return; }
    AdministerCalendars.incrementalSync(channelEntry)
      .then(syncResp => {
	debug('Syncing for calendar update (%s)', channelId);
	return syncResp;
      })
      .then(AdministerCalendars.persistNewSyncToken)
      .then(parseEvents)
      .then(parsedUpdates => {
	calendarEmitter.emit('CALENDAR_UPDATE', parsedUpdates);
      })
      .catch(console.log);
  });
}

// Emit events per a sync response
function emitEvents(syncResponse) {
  if (syncResponse.items.length === 0) {
    debug('No new events found on sync response for %s', syncResponse.calendarId);
    return false;
  }
  calendarEmitter.emit('CALENDAR_UPDATE', parseEvents(syncResponse));
  return true;
}

/**
 * Returns the Channel Entry from Database
 * @param  {String} channelId string of channel entry
 * @return {Object}           Mongoose Virtual Model of Channel Entry
 */
function getChannelEntry(channelId) {
  return ChannelEntry.findOne({ channelId: channelId });
}

function parseEvents(syncResponse) {
  if (!syncResponse.items || syncResponse.items.length === 0) return syncResponse;
  // Event list is order sensitive
  // Filter events for any duplicates and just get the latest one
  var eventList = syncResponse.items
      .filter(_filterForLatestEvents);
  var userId = _parseUserIdFromEmail(syncResponse.summary);
  const updates = eventList.map(event => {
    event.calendarId = syncResponse.summary;
    event.userId = userId;
    return event;
  });

  return updates;
}

// Looks through the list to find any matching event
// previously
// _filterForLatestEvent :: (Element, Index, Array) -> Boolean
function _filterForLatestEvents(currentEvent, currentIndex, list) {
  const mostRecentIndex = _.findIndex(list, (e) => e.id === currentEvent.id);
  // If the current item index is equal or less than the most recentIndex, keep it (true)
  return (currentIndex <= mostRecentIndex) ? true : false;
}

function _parseUserIdFromEmail(email) {
  if (typeof email !== 'string') {
    throw new Error('Email is not a string');
  }

  return email.match(/.+?(?=@)/g)[0];
}

@@ -1321,17 +1321,84 @@
 sp =%3E %7B%0A
-%09
+        AdministerCalendars.persistNewSyncToken(channelEntry);%0A%09    
 debug('S
@@ -1444,16 +1444,20 @@
 elId);%0A%09
+    
 return s
@@ -1478,61 +1478,8 @@
  %7D)%0A
-      .then(AdministerCalendars.persistNewSyncToken)%0A
     
@@ -1531,16 +1531,20 @@
 s =%3E %7B%0A%09
+    
 calendar
@@ -1703,24 +1703,26 @@
 Response) %7B%0A
+  
   if (syncRe
@@ -1750,24 +1750,28 @@
 == 0) %7B%0A    
+  
+  
 debug('No ne
@@ -1837,16 +1837,20 @@
 darId);%0A
+    
     retu
@@ -1861,18 +1861,22 @@
 alse;%0A  
-%7D%0A
+  %7D%0A  
   calend
@@ -1939,16 +1939,18 @@
 se));%0A  
+ 
+ 
 return t
@@ -2170,16 +2170,18 @@
 elId) %7B%0A
+  
   return
@@ -2265,24 +2265,26 @@
 Response) %7B%0A
+  
   if (!syncR
@@ -2356,16 +2356,18 @@
 onse;%0A  
+ 
+ 
 // Event
@@ -2391,16 +2391,18 @@
 nsitive%0A
+  
   // Fil
@@ -2459,16 +2459,18 @@
 est one%0A
+  
   var ev
@@ -2504,16 +2504,18 @@
 s%0A      
+  
 .filter(
@@ -2539,16 +2539,18 @@
 vents);%0A
+  
   var us
@@ -2601,16 +2601,18 @@
 mmary);%0A
+  
   const 
@@ -2642,24 +2642,28 @@
 (event =%3E %7B%0A
+    
     event.ca
@@ -2695,24 +2695,28 @@
 ummary;%0A    
+ 
+   
 event.userId
@@ -2726,24 +2726,28 @@
 userId;%0A    
+   
+ 
 return event
@@ -2752,15 +2752,19 @@
 nt;%0A
+  
   %7D);%0A%0A
+  
   re

Update event controller to persist and pass response