const MongoClient = require('mongodb').MongoClient;
const models = require('../models')

const mongodb_hostname = process.env.MONGODB_HOST || 'localhost';
const mongodb_port = process.env.MONGODB_PORT || 27017;
const mongodb_database = process.env.MONGODB_DATABASE || 'lsp';
const mongodb_url = 'mongodb://' + mongodb_hostname + ':' + mongodb_port;

const client = new MongoClient(mongodb_url, { useNewUrlParser: true, useUnifiedTopology: true });

const bucketMaxSize = 4096;

var _db;
var _devices = MongoClient();
var _data;
var _ipx_data;
var _events;
var _alerts;

var days = function(date) {
  return new Date((date - date%86400) * 1000);
}

var init = async function () {
  client.connect(function (err) {
    if (err) {
      return { error: "Error connecting to DB: " + err }

    } else {
      _db       = client.db(mongodb_database);
      _devices  = _db.collection('devices');
      _data     = _db.collection('data');
      _ipx_data = _db.collection('ipx-data');
      _events   = _db.collection('events');
      _alerts   = _db.collection('alerts');

      ////////////////////////////
      // FLUSH DB BY UNCOMMENTING 
      // _devices.remove(function(err, objects){});
      // _data.remove(function(err, objects){});
      // _ipx_data.remove(function(err, objects){});
      // _events.remove(function(err, objects){});
      // _alerts.remove(function(err, objects){});

      return null;
    }
  });
}

var addData = async function (relay, device, element) {
  try {
    const model = await models.data.validateAsync(element);

    await _data.updateOne(
      {
        device: device,
        date: days(element.date),
        bucketSize: { $lt: bucketMaxSize },
      },
      {
        $addToSet: {
          data: model
        },
        $min: { min: model.value },
        $max: { max: model.value },
        $inc: { bucketSize: 1 },
      },
      {
        upsert: true
      })
      .then(err => {
        return err;
      })
  } catch (err) {
    return err;
  }
}

var addEvent = async function (relay, device, element) {
  try {
    const model = await models.event.validateAsync(element);

    await _events.updateOne(
      {
        device: device,
        date: days(element.date),
        bucketSize: { $lt: bucketMaxSize },
      },
      {
        $addToSet: {
          events: model
        },
        $min: { first: model.date },
        $max: { last: model.date },
        $inc: { bucketSize: 1 },
      },
      {
        upsert: true
      })
      .then(err => {
        return err;
      })
  } catch (err) {
    return err;
  }
}

var addAlert = async function (relay, device, element) {
  try {
    const model = await models.alert.validateAsync(element);

    await _alerts.updateOne(
      {
        device: device,
        relay: relay,
        bucketSize: { $lt: bucketMaxSize },
      },
      {
        $addToSet: {
          alerts: model
        },
        $min: { first: model.date },
        $max: { last: model.date },
        $inc: { bucketSize: 1 },
      },
      {
        upsert: true
      })
      .then(err => {
        return err;
      })
  } catch (err) {
    console.log(err)
    return err;
  }
}

var addIPXData = async function (relay, device, child, element) {
  try {
    const model = await models.ipxdata.validateAsync(element);

    await _ipx_data.updateOne(
      {
        device: device,
        child: child,
        date: days(element.date),
        bucketSize: { $lt: bucketMaxSize },
      },
      {
        $addToSet: {
          data: model
        },
        $min: { first: model.date },
        $max: { last: model.date },
        $inc: { bucketSize: 1 },
      },
      {
        upsert: true
      })
      .then(err => {
        return err;
      })
  } catch (err) {
    return err;
  }
}

exports.init = init

exports.addData = addData
exports.addEvent = addEvent
exports.addAlert = addAlert
exports.addIPXData = addIPXData