package services

import (
	"time"

	"github.com/tgs266/dawn-go-common/common"
	"gitlab.cs.umd.edu/dawn/go-backend/dawn-gdd/models"
	"gitlab.cs.umd.edu/dawn/go-backend/dawn-gdd/models/enums"
	"gitlab.cs.umd.edu/dawn/go-backend/dawn-gdd/persistence"
	"gitlab.cs.umd.edu/dawn/go-backend/dawn-gdd/persistence/entities"
	"gitlab.cs.umd.edu/dawn/go-backend/dawn-gdd/utils"
	"gonum.org/v1/gonum/stat"
)

func GetGddValues(ctx common.DawnCtx, request models.GddRequest) models.GddResponse {
	product := enums.GetProductFromString(request.Product)
	var gdds entities.Gdd
	if request.PlantingDate.Year() == time.Now().Year() {
		gdds = persistence.CurrentGddFindFirstByYearAndLocation(ctx, request.BuildLocation())
	} else if request.PlantingDate.Year() > time.Now().Year() {
		return models.GddResponse{
			Product:          product.Name,
			ClosestLatitude:  gdds.Location.Coordinates[1],
			ClosestLongitude: gdds.Location.Coordinates[0],
			GddValues:        []float64{},
		}
	} else {
		gdds = persistence.GddFindFirstByYearAndLocation(request.PlantingDate.Year(), request.BuildLocation())
	}

	if request.PlantingDate.Year() >= time.Now().Year() {
		pdInt := request.PlantingDate.YearDay() - 1
		gdds.MaxTemps = gdds.MaxTemps[pdInt:]
		gdds.MinTemps = gdds.MinTemps[pdInt:]
	}

	returnGdds := models.GddResponse{
		Product:          product.Name,
		ClosestLatitude:  gdds.Location.Coordinates[1],
		ClosestLongitude: gdds.Location.Coordinates[0],
		GddValues:        utils.CalculateGddValues(gdds.MinTemps, gdds.MaxTemps, product, request.Accumulate),
		LastDate:         gdds.LastDate.Time(),
	}
	return returnGdds
}

func GetNormalValues(request models.GddRequest) models.GddResponse {
	product := enums.GetProductFromString(request.Product)
	gs := persistence.GetLastNormalsYearly(request.BuildLocation())
	var returnGdds models.GddResponse
	var gdds []float64
	rows := [][]float64{}

	// get the int of the planting date. If the date is less than the first date, we do nothing
	// otherwise, we adjust
	// need to do before because of accumulations
	sliceDateInt := request.PlantingDate.YearDay() - 1
	if sliceDateInt < 0 {
		sliceDateInt = 0
	}

	for i := sliceDateInt; i < len(gs[0].MinTemps); i++ { //; i++ {
		row := []float64{}
		for j := 0; j < len(gs); j++ {
			row = append(row, utils.CalculateSingleGdd(gs[j].MinTemps[i], gs[j].MaxTemps[i], product))
			if request.Accumulate && i > sliceDateInt {
				row[j] += rows[len(rows)-1][j]
			}
		}
		rows = append(rows, row)
		mean := stat.Mean(row, nil)
		gdds = append(gdds, mean)
	}

	returnGdds = models.GddResponse{
		Product:          product.Name,
		ClosestLatitude:  gs[0].Location.Coordinates[1],
		ClosestLongitude: gs[0].Location.Coordinates[0],
		GddValues:        gdds,
	}

	return returnGdds
}