gdd_collection = require('../models/gdd.js');
gdd_current_collection = require('../models/gdd_current.js');
gdd_normal_collection = require('../models/normals.js');
utils = require('../lib/utils');

function send_response(message, gdds, data, res) {
    res.json({
        message: message,
        date: data["last_date"],
        data: gdds,
        closest_lon: data["location"]["coordinates"][0],
        closest_lat: data["location"]["coordinates"][1]
    })
}

function find(collection, query, projection, temps, res, product) {
    collection.findOne(query, projection).then(function(data) {
        var min_temps = data["min_temps"]
        var max_temps = data["max_temps"]
        var gdds = [];

        var { t_base, t_max, t_min } = temps;
        
        var min_temp = 0
        var max_temp = 0

        var gdd_sum = 0;
        
        for (var i = 0; i < min_temps.length; i++) {
            gdd_value = utils.calculate_gdd(min_temps[i], t_min, max_temps[i], t_max, t_base, product);
            gdd_sum += gdd_value
            gdds.push(gdd_sum)
        }
        send_response("Accumulated GDDs", gdds, data, res);
    }, function(err) {
        res.status(500).send({"internal error": err})
    })
}


exports.accumulated_gdd = function (req, res) {

    var year = parseInt(req.params.year);
    var product = req.params.product;

    var latitude = parseFloat(req.body.latitude)
    var longitude = parseFloat(req.body.longitude)

    var query = {
        location: { 
            "$near": {
                "$geometry": {
                    "type": "Point", 
                    "coordinates": [longitude, latitude]
                },
            },
        },
        year: year,
    }

    var t_base = 50
    var t_max = 86
    var t_min = 50 

    errors = []

    if (year < 1981 || year > new Date().getFullYear()) {
        errors.push({
            parameter_error: "year",
            message: year.toString() + " is out of bounds for GDD calculations. Must be between 1981 - Current Year"
        });
    }

    if (latitude < 24.083334 || latitude > 49.916668) {
        errors.push({
            parameter_error: "latitude",
            message: latitude.toString() + " is out of bounds for GDD calculations. Must be between 24.083334 - 49.916668"
        });
    }

    if (req.body.hasOwnProperty("t_base")) {
        t_base = parseFloat(req.body.t_base);
        if (t_base < t_min) {
            t_min = t_base;
        }
    } else {
        out = utils.product_base_switch(product, errors, t_base, t_min);
        t_base = out.t_base;
        t_min = out.t_min;
        errors = out.errors;
    }
    

    if (longitude < -125 || longitude > -66.5) {
        errors.push({
            parameter_error: "longitude",
            message: longitude.toString() + " is out of bounds for GDD calculations. Must be between -125.0 - -66.5"
        });
    }

    if (errors.length > 0) {
        res.status(400).send({
            errors: errors
        })
    }

    var projection = {
        min_temps: 1,
        max_temps: 1,
        location: 1,
    }

    temps = {
        t_base: t_base,
        t_max: t_max,
        t_min: t_min,
    }

    if (year != new Date().getFullYear()) {
        find(gdd_collection, query, projection, temps, res, product);
    } else {
        find(gdd_current_collection, query, projection, temps, res, product);
    }
   
};


exports.accumulated_normal_gdd = function (req, res) {

    var product = req.params.product;

    var latitude = parseFloat(req.body.latitude)
    var longitude = parseFloat(req.body.longitude)

    var query = {
        location: { 
            "$near": {
                "$geometry": {
                    "type": "Point", 
                    "coordinates": [longitude, latitude]
                },
            },
        },
    }

    var t_base = 50
    var t_max = 86
    var t_min = 50 

    errors = []

    if (latitude < 24.083334 || latitude > 49.916668) {
        errors.push({
            parameter_error: "latitude",
            message: latitude.toString() + " is out of bounds for GDD calculations. Must be between 24.083334 - 49.916668"
        });
    }

    if (req.body.hasOwnProperty("t_base")) {
        t_base = parseFloat(req.body.t_base);
        if (t_base < t_min) {
            t_min = t_base;
        }
    } else {
        out = utils.product_base_switch(product, errors, t_base, t_min);
        t_base = out.t_base;
        t_min = out.t_min;
        errors = out.errors;
    }
    

    if (longitude < -125 || longitude > -66.5) {
        errors.push({
            parameter_error: "longitude",
            message: longitude.toString() + " is out of bounds for GDD calculations. Must be between -125.0 - -66.5"
        });
    }

    if (errors.length > 0) {
        res.status(400).send({
            errors: errors
        })
    }

    var projection = {
        min_temps: 1,
        max_temps: 1,
        location: 1,
    }

    temps = {
        t_base: t_base,
        t_max: t_max,
        t_min: t_min,
    }

    find(gdd_normal_collection, query, projection, temps, res, product);   
};