#ifndef BufferSpatialCalc_H
#define BufferSpatialCalc_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 <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <algorithm>// for sort
#include <cmath>		
#include "../Inputs/Inputs.h"
#include "../Inputs/TerrainProcessor.h"

//Conversion between (cm*um)/s and m^2/day, 0.000864 = (1/10^6)*((60*60*24)/1)*(1/100) = m/um * s/day * m/cm
# define transmissivity_convert_factor 0.000864
# define two_three 0.66666666666
# define year_to_seconds 31536000 //365 * 24 * 3600
# define ha_to_m2 10000
#define m3_to_L 1000

class BufferSpatialCalc
{
private:
	
	//static  void accLenghtoArea(Inputs* input);
	static void RunoffIndex_Surface_calc(vector<double> FA, vector<double> Slope_Pixel_mpm);
	static void RunoffIndex_Subsurface_calc(Inputs* input, vector<double> FA, vector<double> Slope_Pixel_mpm);
	static void BufferIndex_Surface_calc(vector<double>travel_time);
	static void BufferIndex_Subsurface_calc(vector<double>travel_time);
	
	
	

	//static bool iWEIGHT;
	static void TravelTime_Runoff_Surface_calc(vector <double> slope);
	static void ManningRoughness_HydraulicRadius_CreateMap(Inputs* input);
	static void NutrientTrapping_CreateMap(Inputs* input);
	static void Slope_DispersalArea_calc(vector <double> fdr);
	
	//static void slope_calc(Inputs* input);
	static void Depth_GroundwaterTable_calc(Inputs* input);
	static void TravelTime_Runoff_Subsurface_calc(Inputs* input, vector <double> slope);
	//static void BI_calc(Inputs* input, vector<double>input_travel_time, vector<double>output_BI);
	
	static void filter_to_slope_calc();//for CADA 2003
	
	static double ExportCoefficient_Retrieve_50thPercentile(Inputs* input, string pollutant_type, double lc);
	static double WaterVolume_Retrieve_50thPercentile(Inputs* input, double lc);
	static void ExportCoefficient_unweighted_CreateMap(Inputs* input);
	static void RunoffIndex_BufferIndex_Surface_Ratio_calc();
	static void RunoffIndex_BufferIndex_Subsurface_Ratio_calc();
	//static void ExportCoefficient_Weighted_Surface_calc();
	//static void ExportCoefficient_Weighted_Subsurface_calc();
	//find the  positive, non-nodata, non -nan, non-inf, and non -inf minimumm value
	static double Find_MinimumPositiveValue_1D_Vector_calc(vector<double> vec1D);
	static void Find_PercentileValue_1D_Vector_calc(Inputs* input, vector<double> weightedECvec1D, vector<long double > unweightedECvec1D, bool isSubsurfaceCalculationEnabled);
	static void writeHotspotReport(string filename, vector<tuple<int, int, int, double, double, double, double, double, double, double, double, double, double, double, int>>hotspot_tuple);
	
	static double calculateMedian(vector<double> map);
	static double Find_MaximumPositiveValue_1D_Vector_calc(vector<double> vec1D);

	static double cellsize_m;
	static vector<double> RI_surf, RI_sub, BI_surf, BI_sub;
	static int Flag_TI_Impervious_Accumulated;
	static vector <double> FA_weighted_m;
	static int nRows, nCols;
	static vector<double> Manningn_vec, Hydraulic_R_vec;
	static vector <double> buffer_rise2, buffer_rise1, buffer_rise, buffer_run1, buffer_run, buffer_slope;
	static vector <double> Time_surf1, Time_surf2, Time_surf;
	static vector <double> filter1, filter2, filter, filter_to_slope1, filter_to_slope;
	static vector <double> Time_sub1, Time_sub2, Time_sub;
	static vector <double> s_wtable_est;
	//static vector<vector<double>> S_WTable_2D;
	static vector<vector<double>> slopeorganizer_temp;
	static vector <double> p_release_vec, p_trapping_vec;
	static vector<long double>ec_tn_vec, ec_tp_vec, ec_tss_vec;
	static vector<long double>ec_tn_orig, ec_tp_orig, ec_tss_orig;
	static vector<double>BI_surf_ratio, BI_sub_ratio, RI_surf_ratio, RI_sub_ratio;
	static double BI_surf_avg, BI_sub_avg, RI_surf_avg, RI_sub_avg;
	static double BI_surf_median, BI_sub_median, RI_surf_median, RI_sub_median;
	static vector<double> surf_ec_tp_wtd, surf_ec_tn_wtd, surf_ec_tss_wtd,sub_ec_tp_wtd, sub_ec_tn_wtd, sub_ec_tss_wtd;
	static vector<double> slope_dem, slope_wem, slope_negdem,slope_negwem;
	static double NODATA_code;
	//To determine if two 1D vectors representing maps are not aligned
	static vector<int> hotspot_id_temp;
	static vector<double> hotspot_map_temp;
	static vector<tuple<int, int, int, double, double, double, double, double, double, double, double, double, double, double, int>> hotspot_report_temp;
	static void updateLandCover(Inputs* input);
	static double AverageContributingAreaLoad_calc(int GI_ulcorner_row, int GI_ulcorner_col, int GI_lrcorner_row, int GI_lrcorner_col, string type);
	static vector<double> ca_concentration_tp_mg_L, ca_concentration_tn_mg_L, ca_concentration_tss_mg_L;
	static void ContributingConcentrationValues_calc(Inputs* input);
	static void replacePollutantConcentrations(Inputs* input);
	static void ExportCoefficient_Unweighted_sum_calc();
	static void ExportCoefficient_Weighted_sum_calc(Inputs* input, bool isSubsurfaceCalculationEnabled);
	//static void ExportCoefficient_Weighted_Subsurface_sum_calc();
	static void Normalize_EC_EMC_maps(Inputs* input, bool isSubsurfaceCalculationEnabled);
	static void ReplaceElevationWithVector(vector<double>& source_vector);
	static void ComputeWEM(Inputs* input);
		// Ensure that replacement only occurs if Flag_FlowDirection_Source is set to DEM
	static long double sum_unweighted_ec_tn, sum_unweighted_ec_tp, sum_unweighted_ec_tss,
		sum_weighted_ec_tn, sum_weighted_ec_tp, sum_weighted_ec_tss;
	static vector<double> groundwatertable_elevation1D, neg_groundwatertable_elevation1D;
	static void recomputeFlowDirection(Inputs* input);
	static bool isSubsurfaceCalculationEnabled;

public:
	static void BufferModel_HotSpotMaps_DiffusePollution_main(Inputs* input);
	static void BufferModel_IntermediateOutputs_writer(string file_name);
	static void ReplaceFlowDirectionOrganizerWithVector(vector<double>& source_vector);
	static vector<int> ContributingAreaPixels_map_writeout, DispersalAreaPixels_map_writeout;
	static vector<double> total_ec_tp_wtd, total_ec_tn_wtd, total_ec_tss_wtd;
	static vector<double> total_emc_tp_wtd, total_emc_tn_wtd, total_emc_tss_wtd;
	static bool flag_reduce_EC_EMC_after_GI;
	//static vector <double> imp_weight_m, per_weight_m, area_weight_m;
	static vector <double> waters01, waters0;
	static void ReceivingWater_ZeroValue_CreateMap_from_NHD();
	static void ReceivingWater_ZeroValue_CreateMap_from_DEM();
	static void Contributing_dispersal_CreateMap(int row, int col);
	static bool isPixelValid(int i, Inputs* input);
};

#endif