import log from '../lib/logger-service';
import * as strings from '../coaching-chatbot/strings.json';

module.exports = class InMemoryProvider {
  constructor() {
    this.db = {};
  }

  read(sessionId) {
    log.silly('DB contents: {0}', JSON.stringify(this.db));
    if (this.db[sessionId] === undefined) {
      this.db[sessionId] = {};
    }

    log.silly('Retrieved context for {0}: {1}',
        sessionId, JSON.stringify(this.db[sessionId]));
    return Promise.resolve(this.db[sessionId]);
  }

  readAll() {
    log.silly('DB contents: {0}', JSON.stringify(this.db));
    return this.db;
  }

  readAllWithReminders() {
    log.silly('Getting all sessions with reminders');
    let date = this.getCurrentDateWithOffset();
    let hour = ('0' + date.getHours()).substr(-2, 2);

    return this.filterSessions(date, hour);
  }

  readAllWithFeedbacks() {
    log.silly('Getting all sessions with feedbacks');
    let date = this.getCurrentDateWithOffset(6);
    let hour = ('0' + ((date.getHours() + 23) % 24)).substr(-2, 2);

    return this.filterSessions(date, hour);
  }

  getCurrentDateWithOffset(daysOff = 0) {
    let d = new Date();
    // UTC + 2 -> Suomen aika
    return new Date(d.getTime() +
      (d.getTimezoneOffset() + 120 + daysOff * 24 * 60) * 60 * 1000);
  }

  filterSessions(date, hour) {
    let sessions = [];
    for (let sessionId in this.db) {
      if (!{}.hasOwnProperty.call(this.db, sessionId)) continue;
      log.silly('Evaluating session with id: ', sessionId);
      let context = this.db[sessionId];

      const day = context.weekDay;
      if (day === undefined) continue;
      let meetingDay = strings['@WEEKDAYS'].indexOf(day.toUpperCase());
      if (meetingDay == date.getDay()) {
        if (('0' + context.time).substr(-5, 2) == hour) {
          log.silly('Found context with id: ', sessionId);
          sessions.push( { 'id': sessionId, 'context': context } );
        }
      }
    }
    return Promise.resolve(sessions);
  }

  write(sessionId, context) {
    this.db[sessionId] = context;

    log.silly('Writing context for {0}: {1}',
        sessionId, JSON.stringify(this.db[sessionId]));
    return Promise.resolve(this.db[sessionId]);
  }

  getAvailablePairs(id) {
    return new Promise((resolve, reject) => {
      log.silly('Id: {0}', id);

      let pairs = [];

      for (let sessionId in this.db) {
        if (!{}.hasOwnProperty.call(this.db, sessionId)) continue;

        log.silly('Evaluating possible pair {0}', sessionId);
        if (sessionId == id) continue;
        let session = this.db[sessionId];
        let context = this.db[id];

        if (session.searching === true &&
            (!session.pairRequests || !session.pairRequests.includes(id)) &&
            (!session.rejectedPeers || !session.rejectedPeers.includes(id)) &&
            (session.communicationMethods && context.communicationMethods &&
              Object.keys(session.communicationMethods).some((method) =>
              Object.keys(context.communicationMethods).includes(method)))) {
          log.silly('Found a valid pair!');
          pairs.push({ id: sessionId });
        }
      }

      resolve(pairs);
    });
  }

  dump() {
    return this.db;
  }

  load(data) {
    this.db = data;
  }
};

@@ -2318,128 +2318,359 @@
 let 
-pairs = %5B
+context = this.db%5Bid
 %5D;%0A
-%0A
       
-for (let sessionId in this.db) %7B%0A        if (!%7B%7D.hasOwnProperty.call(this.db, sessionId)) continue;%0A%0A
+if (!context %7C%7C !context.communicationMethods) return resolve(%5B%5D);%0A%0A      let notIn = (prop, content) =%3E !prop %7C%7C !prop.includes(content);%0A      let someCommon = (a, b) =%3E Object.keys(a %7C%7C %7B%7D)%0A            .some((method) =%3E Object.keys(b %7C%7C %7B%7D).includes(method));%0A%0A      resolve(Object.keys(this.db).filter((pairId) =%3E %7B%0A  
     
@@ -2715,23 +2715,20 @@
 r %7B0%7D', 
-session
+pair
 Id);%0A   
@@ -2736,58 +2736,18 @@
     
-if (sessionId == id) continue;%0A        let session
+  let pair
  = t
@@ -2749,31 +2749,28 @@
 r = this.db%5B
-session
+pair
 Id%5D;%0A       
@@ -2774,55 +2774,37 @@
     
-let context = this.db%5Bid%5D;%0A%0A        if (session
+  return id != pairId && pair
 .sea
@@ -2838,42 +2838,18 @@
     
-(!session.pairRequests %7C%7C !session
+notIn(pair
 .pai
@@ -2857,30 +2857,21 @@
 Requests
-.includes(
+, 
 id)
-)
  &&%0A    
@@ -2882,17 +2882,18 @@
     
-(!session
+notIn(pair
 .rej
@@ -2906,403 +2906,142 @@
 eers
- %7C%7C !session.rejectedPeers.includes(id)) &&%0A            (session.communicationMethods && context.communicationMethods &&%0A              Object.keys(session.communicationMethods).some((method) =%3E%0A              Object.keys(context.communicationMethods).includes(method)))) %7B%0A          log.silly('Found a valid pair!');%0A          pairs.push(%7B id: sessionId %7D);%0A        %7D%0A      %7D%0A%0A      resolve(pairs
+, id) &&%0A            someCommon(pair.communicationMethods, context.communicationMethods);%0A        %7D).map((pairId) =%3E (%7B id: pairId %7D))
 );%0A 

Simplify getAvailablePairs