import {EventEmitter} from 'events';

import {
  DCOS_CHANGE,
  MESOS_SUMMARY_CHANGE,
  MARATHON_GROUPS_CHANGE
} from '../constants/EventTypes';
import Framework from '../structs/Framework';
import MarathonStore from './MarathonStore';
import MesosSummaryStore from './MesosSummaryStore';
import ServiceTree from '../structs/ServiceTree';
import SummaryList from '../structs/SummaryList';

const METHODS_TO_BIND = [
  'onMarathonGroupsChange',
  'onMesosSummaryChange'
];

class DCOSStore extends EventEmitter {

  constructor() {
    super(...arguments);

    METHODS_TO_BIND.forEach((method) => {
      this[method] = this[method].bind(this);
    });

    this.data = {
      marathon: new ServiceTree(),
      mesos: new SummaryList(),
      dataProcessed: false
    };

    this.proxyListeners = [
      {
        event: MARATHON_GROUPS_CHANGE,
        handler: this.onMarathonGroupsChange,
        store: MarathonStore
      },
      {
        event: MESOS_SUMMARY_CHANGE,
        handler: this.onMesosSummaryChange,
        store: MesosSummaryStore
      }
    ];
  }

  onMarathonGroupsChange() {
    let groups = MarathonStore.get('groups');
    if (!(groups instanceof ServiceTree)) {
      return;
    }

    this.data.marathon = groups;
    this.data.dataProcessed = true;
    this.emit(DCOS_CHANGE);
  }

  onMesosSummaryChange() {
    let states = MesosSummaryStore.get('states');
    if (!(states instanceof SummaryList)) {
      return;
    }

    this.data.mesos = states;
    this.emit(DCOS_CHANGE);
  }

  addProxyListeners() {
    this.proxyListeners.forEach(function (item) {
      item.store.addChangeListener(item.event, item.handler);
    });
  }

  removeProxyListeners() {
    this.proxyListeners.forEach(function (item) {
      item.store.removeChangeListener(item.event, item.handler);
    });
  }

  addChangeListener(eventName, callback) {
    this.on(eventName, callback);
  }

  removeChangeListener(eventName, callback) {
    this.removeListener(eventName, callback);
  }

  /**
   * Adds the listener for the specified event
   * @param {string} eventName
   * @param {Function} callback
   * @return {DCOSStore} DCOSStore instance
   * @override
   */
  on(eventName, callback) {
    // Only add proxy listeners if not already listening
    if (this.listeners().length === 0) {
      this.addProxyListeners();
    }

    return super.on(eventName, callback);
  }

  /**
   * Remove the specified listener for the specified event
   * @param {string} eventName
   * @param {Function} callback
   * @return {DCOSStore} DCOSStore instance
   * @override
   */
  removeListener(eventName, callback) {
    super.removeListener(eventName, callback);
    // Remove proxy listeners if no one is listening
    if (this.listeners().length === 0) {
      this.removeProxyListeners();
    }

    return this;
  }

  /**
   * @type {ServiceTree}
   */
  get serviceTree() {
    let {marathon, mesos} = this.data;

    // Create framework dict from Mesos data
    let frameworks = mesos.lastSuccessful().getServiceList()
      .reduceItems(function (map, framework) {
        map[framework.name] = framework;

        return map;
      }, {});

    // Merge data by framework name, as  Marathon doesn't know framework ids.
    return marathon.mapItems(function (item) {
      if (item instanceof Framework) {
        return new Framework(
          Object.assign({}, frameworks[item.getName()], item)
        );
      }

      return item;
    });

  }

  get dataProcessed() {
    return this.data.dataProcessed;
  }

  static get storeID() {
    return 'dcos';
  }
}

module.exports = new DCOSStore();

@@ -680,16 +680,39 @@
 arathon:
+ %7B%0A        serviceTree:
  new Ser
@@ -721,16 +721,24 @@
 ceTree()
+%0A      %7D
 ,%0A      
@@ -1136,22 +1136,27 @@
     let 
-groups
+serviceTree
  = Marat
@@ -1189,22 +1189,27 @@
   if (!(
-groups
+serviceTree
  instanc
@@ -1275,17 +1275,34 @@
 thon
- = groups
+.serviceTree = serviceTree
 ;%0A  
@@ -2963,16 +2963,30 @@
 marathon
+:%7BserviceTree%7D
 , mesos%7D
@@ -3136,18 +3136,19 @@
 ction (m
-ap
+emo
 , framew
@@ -3163,18 +3163,19 @@
        m
-ap
+emo
 %5Bframewo
@@ -3213,18 +3213,19 @@
 return m
-ap
+emo
 ;%0A      
@@ -3322,24 +3322,27 @@
  return 
-marathon
+serviceTree
 .mapItem

Refactor DCOSStore data structure and handler