'use strict';

var EventEmitter    = require('events').EventEmitter
  , configValidator = require('./configValidator')
  , pull            = require('../wrappers/pull')

/**
 * Default DataService, pulls data from the server via ajax.
 * Will poll the server for data at regular intervals based on config
 *
 * DataServices provide the following interface
 * on('data') - consumers listen to dataservice for data events
 * getData()  - upon receiving a data event consumers call getData
 * start()    - Starts the dataservice
 */
class DataService extends EventEmitter {

  //@param config {object}
  constructor(config) {
    // Validation throws errors if fails
    configValidator(['type', 'request', 'refresh'], config)
    configValidator(['url'], config.request)

    this.config = config
    this.url = config.request.url
    this.refresh = config.refresh
    this.data = []
  }

  //fetches whatever data the dataservice is holding
  //@return {object}
  getData() {
    return this.data
  }

  //starts the dataservice running
  start() {
    if (!this.isActive) {
      this.pullData()
      this.timer = setInterval(
        this.pullData.bind(this), this.refresh
      )
    }
  }

  stop() {
    clearInterval(this.timer)
    delete this.timer
  }

  get isActive() {
    return !!this.timer
  }

  pullData() {
    var ds = this
    pull(this.config, (err, data) => {
      if (data) {
        ds.data = data
        ds.emit('data')
      }
    })
  }
}

class SinglePollDataService extends DataService {

  //@param config {object}
  constructor(config) {
    configValidator(['type', 'request'], config)
    configValidator(['url'], config.request)

    this.config = config
    this.url = config.request.url
    this.data = []
  }

  start() {
    this.pullData()
  }

  stop() {
    //noop
  }
}

/**
 * DataService for handling Server Sent Events
 * Performs a pull same as a longpoll DataService then sets up a listener for
 * server sent events to continue receiving updates from the server
 */
class SSEDataService extends DataService {

  //@overide
  constructor(config) {
    configValidator(['type', 'request'], config)
    configValidator(['url'], config.request)

    this.config = config
    this.url = config.request.url
    this.data = []
  }

  //@overide
  start() {
    pull(this.config, (err, data) => {
      this.data = data
      this.emit('data')
      //TODO: implement SSE setup
    })
  }
}

/**
 * Module interface
 * @param  {object} config
 * @return {DataService}
 */
module.exports = function(config) {
  var dataServices = {
    sse: (config) => new SSEDataService(config),
    longPoll: (config) => new DataService(config),
    singlePoll: (config) => new SinglePollDataService(config)
  }

  return dataServices[config.type](config)
}

@@ -867,32 +867,59 @@
  this.data = %5B%5D%0A
+    this.isLoading = false%0A
   %7D%0A%0A  //fetches
@@ -1363,16 +1363,73 @@
  = this%0A
+    if (!this.isLoading) %7B%0A      this.isLoading = true%0A  
     pull
@@ -1455,24 +1455,57 @@
  data) =%3E %7B%0A
+        this.isLoading = false%0A  
       if (da
@@ -1518,16 +1518,18 @@
         
+ 
+ 
 ds.data 
@@ -1531,24 +1531,26 @@
 data = data%0A
+  
         ds.e
@@ -1571,16 +1571,26 @@
     
-%7D%0A    %7D)
+  %7D%0A      %7D)%0A    %7D
 %0A  %7D

Add gaurd against sending simultaneous requests