text: 'use strict';
  
  const http = require('http');
  const util = require('util');
  const EventEmitter = require('events').EventEmitter;
  
  // Individual stock data
  var stockData = {
      date: null,
      open: 0,
      close: 0,
      high: 0,
      low: 0,
      volume: 0,
      adjClose: 0,
      fifty: 0,
      twoHundred: 0
  };
  
  // Create stock data collector object
  var StockDataCollector = function() {
      EventEmitter.call(this);
  
      this.createYahooStockUrl = function (symbol, dateFrom, dateTo) {
          if (!dateFrom && !(dateFrom instanceof Date) && !dateTo && !(dateTo instanceof Date) && !symbol && symbol !== "") {
              return "";
          }
  
          var url = "http://real-chart.finance.yahoo.com/table.csv?s=";
          url += symbol + "&g=d";
          url += "&d=" + dateTo.getUTCMonth() + "&e=" + dateTo.getUTCDay() + "&f=" + dateTo.getUTCFullYear();
          url += "&a=" + dateFrom.getUTCMonth() + "&b=" + dateFrom.getUTCDay() + "&c=" + dateFrom.getUTCFullYear() + "&ignore=.csv";
  
          return url;
      };
  
      this.parseStockData = function (data) {
          var splitData = data.split('\n');
  
          if (typeof splitData === "undefined" || !splitData || !splitData.length || splitData.length < 2) {
              return null;
          }
  
          var header = splitData[0];
          var values = splitData.slice(1);
          var stockData = [];
  
          values.forEach(function (element, index, array) {
              if (element && element.trim() !== "") {
                  var splitData = element.split(',');
                  var stock = Object.create(stockData);
  
                  stock.date = Date.parse(splitData[0]);
                  stock.open = Math.round(splitData[1] * 100) / 100;
                  stock.high = Math.round(splitData[2] * 100) / 100;
                  stock.low = Math.round(splitData[3] * 100) / 100;
                  stock.close = Math.round(splitData[4] * 100) / 100;
                  stock.volume = splitData[5] >>> 0;
                  stock.adjClose = Math.round(splitData[6] * 100) / 100;
  
                  stockData.push(stock);
              }
          });
  
          // Sort data in ascending order of date
          stockData.sort(function (a, b) {
              if (a.date > b.date) {
                  return 1;
              }
  
              if (a.date < b.date) {
                  return -1;
              }
  
              // a must be equal to b
              return 0;
          });
  
          var fifty = 0;
          var twoHundred = 0;
  
          // Calculate fifty and two hundred moving day averages
          stockData.forEach(function (element, index, array) {
              if (index > 1) {
                  var fiftyArray = array.slice(Math.max(index - 50, 0), index);
  
                  fifty = fiftyArray.map(function (d) { return d.adjClose }).reduce(function (previousValue, currentValue, index, array) {
                      return previousValue + currentValue;
                  }) / fiftyArray.length;
  
                  var thArray = array.slice(Math.max(index - 200, 0), index);
  
                  twoHundred = thArray.map(function (d) { return d.adjClose }).reduce(function (previousValue, currentValue, index, array) {
                      return previousValue + currentValue;
                  }) / thArray.length;
              } else {
                  fifty = element.adjClose;
                  twoHundred = element.adjClose;
              }
  
              element.fifty = fifty;
              element.twoHundred = twoHundred;
          });
  
          // Minmize data to return
          stockData = stockData.map(function (element) {
              return { date: element.date, adjClose: element.adjClose, fifty: element.fifty, twoHundred: element.twoHundred };
          });
  
          return { "headers": header.split(','), "data": stockData };
      };
  
      this.getData = function (symbol, fromDate, toDate) {
          var stockUrl = this.createYahooStockUrl(symbol, fromDate, toDate);
          var self = this;
  
          if (stockUrl === "") {
              self.emit('error', '[stockDataCollector.getData] Invalid stock URL.');
          } else {
              http.get(stockUrl, function (res) {
                  var rawStockData = "";
                  var responseCode = res.statusCode >>> 0;
  
                  // Ensure valid response code on request
                  if (responseCode != 200) {
                      self.emit('error', "[stockDataCollector.getData] Got invalid response code: " + responseCode);
                      return;
                  }
  
                  // Ensure return type is text-csv
                  if (JSON.stringify(res.headers["content-type"]) !== "\"text/csv\"") {
                      self.emit('error', "[stockDataCollector.getData] Got invalid response type: " + JSON.stringify(res.headers["content-type"]));
                      return;
                  }
  
                  res.on("data", function (chunk) {
                      rawStockData += chunk;
                  });
  
                  res.on("end", function () {
                      self.emit('success', rawStockData);
                  });
              }).on('error', function (e) {
                  self.emit('error', "[stockDataCollector.getData] Got error: " + e.message);
              });
          }
      }
  };
  
  util.inherits(StockDataCollector, EventEmitter);
  
  module.exports = new StockDataCollector();