#ifndef WeatherProcessor_H
#define WeatherProcessor_H
/*
* HydroPlus is source code and models developed and managed by Theodore Endreny and his students at SUNY ESF, te@esf.edu
* The US Forest Service and Davey Tree have provided strategic software development support through funding and personnel
* Attribution for use of software and code is requested. Please see Executive.cpp for documentation.
*/
#include <vector>
#include <iostream>
#include <numeric>
#include <string>
#define _USE_MATH_DEFINES
#include <math.h>
#include <algorithm> 
#include <numeric> 
#include "../DataOrganizer.h"
#include <climits>
//#include "Projections.h"

//Forward declaration of class Inputs
class Inputs;

#define meterofdgree 111000; 
//Conversion km to m
#define Ratio_km_to_m 1.0/1000.0
//Constant environmental lapse rate dry (ELR) air (from Stull, 2000, estimated as Gamma_elr = 5.5 C/km), ...
//Note: ... there is no ELR equation but is often between 5 and 6 C/km, hence the estimate of 5.5 C.km
#define Gamma_EnvironmentalLapseRate_C_p_km 5.5
//Constant adiabatic lapse rate dry air (from Stull, 2000, defined after Eq 5.13, Gamma_d = 9.8 C/km)
//Note: Adiabatic lapse rate dry air is not used for estimating air 2 m above ground when summiting a mountain 
#define Gamma_dry_C_p_km 9.8
//Constant adiabatic lapse rate dew point air (from Stull, 2000, derived from Eq 5.8; 1/0.125 = 1/Z_lcl * (T - Td), if Z_lcl=1 km, T=9.8 then Td=1.8)
#define Gamma_dew_C_p_km 1.8


class WeatherProcessor
{
public:
	static vector<long double>  Distance_Pixel_to_Station_vec_km, Weight_StationInverseDistance_vec_frac, Distance_InverseSquared_vec;
	static vector<string>  OBJECTID_shortest, USAF_shortest, WBAN_shortest, Path_folder_shortest, TI_option_shortest;
	static vector<long double> Easting_shortest, Northing_shortest, Elev_m_shortest, Distance_shortest, Slope_deg_shortest, Aspect_deg_shortest, NLCD_Class_shortest, TC_per_shortest, IC_per_shortest, SVeg_in_Gap_frac_shortest, Station_AH_Flux_Wpm2_shortest;
	//static vector<long double> albersEasting_shortest, albersNorthing_shortest;
	
	static void CalcWeightsandRead(long double PixelCenter_easting_m, long double PixelCenter_northing_m, Inputs* input, int DataDrawer_ID);
	static void WeatherStationDistance_sort(Inputs* input, long double PixelCenter_easting_m, long double PixelCenter_northing_m);
	static void MapPixelNearestWeatherStationWriter( Inputs* input);
	static void WeatherStationInformationWriter(Inputs* input);
	static void MapPixelWeightedWeatherInputsWriter(Inputs* input);
	static void ComputeSpatiallyWeighted_Weather_Inputs(Inputs* input, int pixelID, int timeStep);
	static void WeatherDataReadandProcessing(Inputs* input, DataOrganizer* organizer);
	//ComputeSpatiallyWeighted_Tair_DEM_Variables function will compute the spatially weighted meteorological variables
	static void ComputeSpatiallyWeighted_Tair_DEM_Variables(Inputs* input, int StationID_int, int DataDrawer_ID, int timeStep);
	static void ComputeSpatiallyWeighted_DegreeHour(Inputs* input, int MapPixel_ID);
	static void MapPixelCalcWeightsandRead(Inputs* input, DataOrganizer* organizer);
	static void MapCenterCalcWeightsandRead(Inputs* input);
	static void readMultipleWeatherStations_List_CSV(Inputs* input);
	static void readWeatherFile(Inputs* input);
	static void readEvaporationFile(Inputs* input);
	static void readRadiationFile(Inputs* input);
	static void VectorsOfWeatherData(Inputs* input, istream& lineWeatherFile, bool Flag_SavingSimulationTimeRange, bool Flag_ProcessTimeStep, bool Flag_SavingAllRecord);
	static void Get_DaylightSavingTime_Periods(int SimulationDateStart_YYYYMMDDHH, int SimulationDateStop_YYYYMMDDHH, vector<pair<int, int>>& DaylightSaving_StartStopPairs_YYYYMMDDHH);
	static void Apply_DaylightSavingTime_Adjustment(int orig_GD, int orig_HH, int& new_GD, int& new_GDH, string& new_HMS);
	static bool IsDuring_DaylightSavingTime(int dateTime_YYYYMMDDHH, const vector<pair<int, int>>& DaylightSavingTime_Pairs); 
	static void Update_SimulationTime_Vectors(Inputs* input, int Date_YYYYMMDD, string Time_HHMMSS_str, int date_InputDataRow_HH, int date_InputDataRow_GDH, bool Flag_OutputTime_DST, const vector<pair<int, int>>& DaylightSaving_StartStopPairs_YYYYMMDDHH, int Flag_Update_SimulationDate_GD_GDH);
	
	static vector<pair<int, int>> DaylightSaving_StartStopPairs_YYYYMMDDHH;

	static vector<int> SimulationDate_GD_AllRecord, SimulationDate_GDH_AllRecord, SimulationDate_HH_AllRecord;
	static vector<string> SimulationTime_HMS_AllRecord;
	static vector<double> RadiationNet_Wpm2_AllRecord, Tair_C_AllRecord, Tdew_C_AllRecord, Rain_m_AllRecord, Snow_m_AllRecord, WindSpd_mps_AllRecord, WindDir_deg_AllRecord, AtmPres_kPa_AllRecord, Precip_mpdt_AllRecord;
	static int SimulationDate_Hottest_GD;
	static string SimulationTime_Hottest_HMS;
	static int SimulationDateStart_GDH, SimulationDateStop_GDH;

	//saving detailed info of stations for the hottest day
	static map<string, vector<double> > WeatherMap, EvaporationMap, RadiationMap;
	static map<string, double> LatitudeMap;
	static map<int, map<int, vector<string> > > PixelNearestStation;
	//saving basic info of a station, including the hottest day
	static map<string, vector<string> > StationInfoMap;
	//StationMapID vector will contain string integers as ID to each weather station that has influence across maps used in simulation
	//static vector<string> StationMapID;
	
	static map<int, map<string, vector<double> > > WeightedInputMap;
	
	//Tair_Mesoscale_byStationID_K is 2D vector with (ID)(Tair_K)
	static map<int, vector<double>> Tair_Mesoscale_byStationID_K;
	//AbsHumidity_Mesoscale_byStationID_kg_p_m3 is 2D vector with (ID)(AbsHumidity_kg_p_m3)
	static map<int, vector<double>> AbsHumidity_Mesoscale_byStationID_kg_p_m3;
	//Tair_weighted_K and Tdew_weighted_K (K) are spatially weighted values of station air temperature, corrected for elevation
	static double Tair_weighted_K, Tdew_weighted_K;
	//Tair_mesoScale_weighted_K and AbsHumidity_mesoScale_weighted_kg_p_m3 are spatially weighted values of station mesoscale air temperature, corrected for elevation
	static double Tair_mesoScale_weighted_K, AbsHumidity_mesoScale_weighted_kg_p_m3;
	//Tair_mesoScale_final_byStationID_K is 2D vector with (ID)(Tair_mesoScale_final_K)
	static map<int, vector<double>> Tair_mesoScale_final_byStationID_K;
	//H_total_byStationID_W_p_m2 is 2D vector with (ID)(H_total_W_p_m2)
	static map<int, vector<double>> H_total_byStationID_W_p_m2;
	//Tair_mesoScale_final_weighted_K is spatially weighted values of station
	static double Tair_mesoScale_final_weighted_K;
	//H_total_weighted_W_p_m2 is spatially weighted values of station
	static double H_total_weighted_W_p_m2;

	static int Date_YYYYMMDD, Time_HHMMSS, timeStepMetData, previous_YYYYMMDD, previous_HMS;
	static string Time_HHMMSS_str;
	static vector<int> SimulationDate_HH;


	//static bool Flag_SearchHottestDay;
	//static int Date_Hottest_YYYYMMDD;
	static string ReadStation_path, ReadStationID;
	static int Actual_hottest_GDH_index;

	static vector<long double> Map_Easting_X_m_vec;
	static vector<long double> Map_Northing_Y_m_vec;
	static int centerMapPixel_ID;
	static vector<double> DegreeHour_Year_Cooling_Ratio_vec, DegreeHour_Year_Heating_Ratio_vec, DegreeHour_Month_Cooling_Ratio_vec, DegreeHour_Month_Heating_Ratio_vec, DegreeHour_Hour_Cooling_K_vec, DegreeHour_Hour_Heating_K_vec;
	static map<int, vector<double>> DegreeHour_Year_Cooling_Ratio_StationID_vec_map, DegreeHour_Year_Heating_Ratio_StationID_vec_map, DegreeHour_Month_Cooling_Ratio_StationID_vec_map, DegreeHour_Month_Heating_Ratio_StationID_vec_map, DegreeHour_Hour_Cooling_K_StationID_vec_map, DegreeHour_Hour_Heating_K_StationID_vec_map;
	static map<int, vector<double>> DegreeHour_Year_Cooling_Ratio_Weighted_vec_map, DegreeHour_Year_Heating_Ratio_Weighted_vec_map, DegreeHour_Month_Cooling_Ratio_Weighted_vec_map, DegreeHour_Month_Heating_Ratio_Weighted_vec_map, DegreeHour_Hour_Cooling_K_Weighted_vec_map, DegreeHour_Hour_Heating_K_Weighted_vec_map;

	static void DegreeHour_CreateRatios_From_Sums_by_YearMonthHour(Inputs* input, string DegreeHour_statisticMethod, int StationID);
	static void DegreeHour_SumHeatingCooling_by_YearMonthHour(Inputs* input, double tempTair_K, int Year_YYYY, int Month_MM, int Hour_HH, string DegreeHour_statisticMethod);
	static int Climate_Year_Start_YYYY;

private:
	static long double toRadians(const long double degree);
	static long double Distance_Calc_LatLong(long double pixelcenter_lat, long double pixelcenter_long, long double station_lat, long double station_lon);
	static long double Distance_Calc_EastingNorthing(long double PixelCenter_x, long double PixelCenter_y, long double Station_easting_m, long double Station_northing_m);
	static void resizeWeatherVectors(Inputs* input);
	static void clearWeatherVectors(Inputs* input); 
	static string to_string_fixed(double value, int precision);
	static long double PixelCenter_X_MapLowerLeft_m, PixelCenter_Y_MapLowerLeft_m;
	string Directory_Input_CLArg;
	static int calculateTimeStep(int current_YYYYMMDD, int current_HMS, int previous_YYYYMMDD, int previous_HMS, int defaultStep_sec);

	static bool isMissing(const string& variable_input);
	static double safe_stod(const string& variable_input, const string& var_name, int line_num);
	static int safe_stoi(const string& variable_input, const string& var_name, int line_num);
	static bool check_column_count(const string& line_of_input, int expected_columns, int line_num);
	static void check_range(double value_of_input, const string& var_name, int line_num, double min_val, double max_val);
	static void WriteDegreeHourToCSV(bool isMultipleStation);
	static void TrimWeatherMapToAdjustedTimesteps(int adjustedTimesteps, map<string, vector<double>>& StationDataMap);

	static double DegreeHour_Threshold_K;
	static string DegreeHour_statisticMethod;
	static bool Flag_DegreeHour_Simulated;
	static int Global_Adjusted_Timesteps;

	static map<int, double>  DH_Cooling_Year_sum, DH_Cooling_Month_sum, DH_Cooling_Hour_sum, DH_Heating_Year_sum, DH_Heating_Month_sum, DH_Heating_Hour_sum;
	static map<int, int>  DH_Year_Cooling_count, DH_Year_Heating_count, DH_Month_Cooling_count, DH_Month_Heating_count, DH_Hour_Cooling_count, DH_Hour_Heating_count;
	static int DH_data_Cooling_total_count, DH_data_Heating_total_count;
	static double DH_Cooling_total_sum, DH_Heating_total_sum;

	static map<int, vector<double>>  DegreeHour_Cooling_Year_abs_K_vec, DegreeHour_Cooling_Month_abs_K_vec, DegreeHour_Cooling_Hour_abs_K_vec, DegreeHour_Heating_Year_abs_K_vec, DegreeHour_Heating_Month_abs_K_vec, DegreeHour_Heating_Hour_abs_K_vec;
	static vector<double> DegreeHour_Cooling_All_abs_K_vec, DegreeHour_Heating_All_abs_K_vec;
	static bool Flag_Tair_degrees_F;
	static bool Flag_Tdew_degrees_F;
};
#endif