/**
* Created by marti on 30/01/2016.
*/
let http = require('http'), request = require('request'), cheerio = require(
    'cheerio'), util = require('util');
const cron = require('node-cron');
const dateFormat = require('dateformat');
const jsonfile = require('jsonfile');
let fs = require('fs');
//var nano = require('nano')('http://martind2000:1V3D4m526i@localhost:5984');
const log4js = require('log4js');
const logger = log4js.getLogger();
const calHandler = require('./today/calHandler');
const swedishWord = require('./today/swedishword');
const weather = require('./today/weather');
const trains = require('./today/trains');
const history = require('./today/history');
const mdMailer = require('./today/mailer');
const mdFitbit = require('./today/fitbit');
const todayFTSE = require('./today/todayftse');
const quotes = require('./today/quotes');
//var db_name = 'silvrgit';
//var dbCloudant = nano.use(db_name);

/*

 We've moved to cloudant through IBM Bluemix for the database

 https://25f854ee-1b51-49ff-acd9-5b0ff478d944-bluemix.cloudant.com/dashboard.html#usage


 */

const credentials = {
    "username": "25f854ee-1b51-49ff-acd9-5b0ff478d944-bluemix",
    "password": "8e417af1b0462ca55726848846cc6b8696fc76defe9d1864cbc334be59549e0c",
    "host": "25f854ee-1b51-49ff-acd9-5b0ff478d944-bluemix.cloudant.com",
    "port": 443,
    "url": "https://25f854ee-1b51-49ff-acd9-5b0ff478d944-bluemix:8e417af1b0462ca55726848846cc6b8696fc76defe9d1864cbc334be59549e0c@25f854ee-1b51-49ff-acd9-5b0ff478d944-bluemix.cloudant.com",
    "database": "keeper"
};

const Cloudant = require('cloudant');
const cloudant = Cloudant({account: credentials.username, password: credentials.password});

const dbCloudant = cloudant.db.use(credentials.database);



require('sugar-date');

String.prototype.hashCode = function() {

    if (Array.prototype.reduce) {
      return this.split('').reduce(function(a,b) {a = ((a << 5) - a) + b.charCodeAt(0);return a & a},0);
    } else {

      let hash = 0, i, chr, len;
      if (this.length == 0) return hash;
      for (i = 0, len = this.length; i < len; i++) {
        chr   = this.charCodeAt(i);
        hash  = ((hash << 5) - hash) + chr;
        hash |= 0; // Convert to 32bit integer
      }
      return hash;
    }
  };

let todayCache = {
    last: 0, data: {
        trains: {last: 0, data: []},
        weather: {},
        history: [],
        today: '',
        tv: {entries: []},
        cal: {today: [], tomorrow: [], week: []},
        swedish: {},
        fitbit: {},
        ftse: {}
    }, expire: ((60 * 1000) * 60)
};
const file = __dirname + '/' + 'newdata.json';
let htmlfile = __dirname + '/' + 'today.html';
let eventEmitter;

function runable() {
  try {
    const now = new Date().getTime();

    console.log('last updated', ((now - todayCache.last) / 60000));
    if (now - todayCache.last < 3600000) {
      return false;
    } else {
      todayCache.last = now;
      return true;
    }
  }
  catch (e) {
    todayCache.last = new Date().getTime();
    return true;

  }

}

function broadcastWeather() {
  const wData = {
    temperature: todayCache.data.weather.data.currently.temperature,
    icon: todayCache.data.weather.data.currently.icon,
    summary: todayCache.data.weather.data.currently.summary
  };

  if (todayCache.data.weather.data.hasOwnProperty('alerts')) {
    wData.alerts = todayCache.data.weather.data.alerts;
  }
  eventEmitter.emit('sendSocket', {id: 'weather', data: wData});
}

function loadData() {
  console.log('Loading old data');
  try {
    todayCache = jsonfile.readFileSync(file);
  }
  catch (e) {
    console.error('Could not load previous data');
  }
}
function saveData() {
  todayCache.last = new Date().getTime();
  logger.info('Saving...');
  jsonfile.writeFileSync(file, todayCache);
}
function saveToDB(data) {
  saveData();

  logger.debug('Inserting into couch...');
  // Logger.info(util.inspect(obj));
  dbCloudant.insert(data, function(err, body, header) {
    if (err) {
      logger.error('Error inserting into couch');
      logger.error(err);
      return;
    }
  });
}

function nth(d) {
  //  If (d > 3 && d < 21) {return 'th';} // Thanks kennebec
  //  if (d % 10 === 1) {return 'st';} else if (d % 10 === 2) {return 'nd';} else if (d % 10 === 3) {return 'rd';} else {return 'th';}
  const n = d;
  return Math.floor(n / 10) === 1 ? 'th' : (n % 10 === 1 ? 'st' : (n % 10 === 2 ? 'nd' : (n % 10 === 3 ? 'rd' : 'th')));
}

function dayNumber() {
  const now = new Date();
  const start = new Date(now.getFullYear(), 0, 0);
  const diff = now - start;
  const oneDay = 1000 * 60 * 60 * 24;
  return Math.floor(diff / oneDay);
}

function breakDay() {
  const now = new Date();
  return {
    year: now.getFullYear(),
    month: parseInt(now.getMonth()) + 1,
    day: now.getDate()
  };
}

function reduceTrains(d) {

  const titles = [], ta = [];
  console.log('reducetrains',d);
  for (let items in d) {
    if (typeof d[items].title !== 'undefined') {
      const hash = d[items].title.hashCode();
      if (titles.indexOf(hash) === -1) {
        titles.push(hash);
        ta.push(d[items]);
      }

    }

  }
  return ta;
}

/**
 * @return {number}
 */
function DayDiff(CurrentDate) {
  const TYear = CurrentDate.getFullYear();
  const TDay = new Date('January, 01, ' + (parseInt(TYear) + 1));
  TDay.getFullYear(TYear);
  let DayCount = (TDay - CurrentDate) / (1000 * 60 * 60 * 24);
  DayCount = Math.round(DayCount);

  const d = new Date();
  DayCount = d.daysSince('beginning of this year');
  return (DayCount);
}

Array.prototype.indexOfOld = Array.prototype.indexOf;
Array.prototype.indexOf = function(e, fn) {
  if (!fn) {
    return this.indexOfOld(e);
  } else {
    if (typeof fn === 'string') {
      const att = fn;
      fn = function(e) {
        return e[att];
      };
    }
    return this.map(fn).indexOfOld(e);
  }
};

module.exports = {
  setEmitter: function(newEmitter) {
    console.log('Setting events', newEmitter);
    eventEmitter = newEmitter;
  }, getClock: function(req, res) {
    //   Console.log(todayCache);
    res.render('pages/clock', todayCache);
  }, getToday: function(req, res) {
    logger.info(todayCache);
    res.render('pages/today', todayCache);
  }, getData: function(req, res) {
    res.setHeader('Content-Type', 'application/json');
    res.end(JSON.stringify(todayCache));
  }, getTodayDate: function() {
    let s;
        const d = new Date();
        let nextYear = (parseInt(d.getFullYear()) + 1).toString() + '-01-01';

    console.log(d.daysUntil('beginning of next year'));
    const daysSinceStart = d.daysSince('beginning of this year');
    const daysRemaining = d.daysUntil('beginning of next year');

    todayCache.data.history = [];
    s = '<strong>' + d.format('{Weekday} {Month} {dd}, {yyyy}') + '</strong> - ';

    s = s + 'The ' + daysSinceStart + nth(daysSinceStart) + ' day of ' + dateFormat(
            d,
            'yyyy') + ', and there are ' + daysRemaining + ' days left until the end of the year.';

    logger.debug(s);
    todayCache.data.today = s;
  },
  refreshTrain: function() {

    trains.updateTrains()
        .then((d) => {
          'use strict';

          d = reduceTrains(d);
          console.log('Trains: ', d);

          eventEmitter.emit('sendSocket', {id: 'trains', data: d});
          todayCache.data.trains.data = d;
          todayCache.data.trains.last = new Date();
        })
        .catch((e)=> {
          'use strict';
          console.error(e);
        });


  },
  refreshWeather: function() {
    weather.newDoGetWeather()
        .then((d) => {
          todayCache.data.weather = d;
          console.log('Updating weather');
          broadcastWeather();
        }).catch((e) => {
      logger.error(e);
    });

  },

  refreshTrainAndWeather: function() {
    this.refreshTrain();
    this.refreshWeather();
  }, preLoadToday: function() {
    module.exports.getTodayDate();
    todayCache.data.cal = {today: [], tomorrow: [], week: []};
    weather.newDoGetWeather()
        .then((d)=> {
          todayCache.data.weather = d;
        })
        .catch((e) => {
          logger.error(e);
        });
    trains.updateTrains()
        .then((d) => {
          'use strict';
          console.log('Trains: ', d);
          todayCache.data.trains.data = d;
          todayCache.data.trains.last = new Date();
        })
        .catch((e)=> {
          'use strict';
          console.error(e);
        });
    history.updateHistory()
        .then((d) => {
          'use strict';
          console.log('History result: ', d);
          todayCache.data.history = d;
        })
        .catch((e)=> {
          'use strict';
          console.error(e);
        });

    calHandler.getSimpleCalV3(
        'http://www.pogdesign.co.uk/cat/download_ics/60cfdff469d0490545d33d7e3b5c0bcc')
        .then((d) => {
          'use strict';
          todayCache.data.tv = d;
        })
        .catch((e) => {
          'use strict';
          logger.error(e);
        });

    todayFTSE.getFTSE()
        .then((d) => {
          todayCache.data.ftse = d;
        })
        .catch((e) => {
          logger.error(e);
        });

    quotes.GetQuotes()
            .then((d) => {
              todayCache.data.quotes = d;
            })
            .catch((e)=> {
              logger.error(e);
            });



    for (let t = 0; t < calHandler.calendars.length; t++) {
      calHandler.getAdvancedCalV3(calHandler.calendars[t])
          .then((d) => {
            'use strict';
            todayCache.data.cal.today = todayCache.data.cal.today.concat(d.today);
            todayCache.data.cal.tomorrow = todayCache.data.cal.tomorrow.concat(d.tomorrow);
            todayCache.data.cal.week = todayCache.data.cal.week.concat(d.week);
          })
          .catch((e) => {
            'use strict';
            logger.error(e);
          });
    }

    swedishWord.getSwedishWord()
        .then((d) => {
          'use strict';
          console.log('Swedish result: ', d);
          todayCache.data.swedish = d;
        })
        .catch((e)=> {
          'use strict';
          console.error(e);
        });

    mdFitbit.getYesterdayFitbit()
        .then((d) => {
          todayCache.data.fitbit = d;
        })
        .catch((e)=> {
          'use strict';
          console.error(e);
        });

    todayCache.date = breakDay();
  }, broadcast: function() {
    console.log('BROADCAST');
    broadcastWeather();
    eventEmitter.emit('sendSocket', {id: 'trains', data: todayCache.data.trains.data});

  }
};

setTimeout(function() {
  loadData();
  if (runable()) {
    module.exports.preLoadToday();
  }
  //Module.exports.preLoadToday();

}, 5000);

setTimeout(function() {
  // mdMailer.sendEmailV1(todayCache, __dirname);
  // saveToDB(todayCache);
  saveData();
}, 45000);

setInterval(function() {

  // EventEmitter.emit('sendSocket',{id:'weather',data:todayCache.data.weather});
  // broadcastWeather();
  // eventEmitter.emit('sendSocket', {id: 'trains', data: todayCache.data.trains.data});


}, (60000));


cron.schedule('30 6 * * *', function() {
  if (runable()) {
    module.exports.preLoadToday();
  }

  return -1;
});

cron.schedule('0 */1 * * *', function() {
  //  Module.exports.refreshTrainAndWeather();
  //  this.refreshTrain();
  module.exports.refreshWeather();

  return -1;
});

cron.schedule('*/15 * * * *', function() {
  module.exports.refreshTrain();

  //  Module.exports.refreshWeather();

  return -1;
});

cron.schedule('45 6 * * *', function() {
  mdMailer.sendEmailV1(todayCache, __dirname);
  saveToDB(todayCache);
  // Console.log('tick');
  return -1;
});


