#include "WaterQuality_Output.h"

//WaterQuality_Output::writeLoad_by_EMC_via_Catchment_TS writes EMC loads at each time step
//Note: Pollutant_Name vector used below are from Pollutants.csv, read in Inputs.cpp into vector 
void WaterQuality_Output::writeLoad_by_EMC_via_Catchment_TS(Inputs *input, int timeStep)
{
	//TimeSeries_Pollutants_kg.csv will hold loads in values of kg
	string path_out = input->SimulationStringParams["OutputFolder_Path"] + "TimeSeries_Pollutants_Catchment_kg.csv";
	//dateVec stores SimulationDate_Output_GD as YYYYMMDD
	vector<int> dateVec = input->SimulationDate_Output_GD;
	//timeVec stores SimulationTime_Output_HMS as HH:MM:DD
	vector<string> timeVec = input->SimulationTime_Output_HMS;
	//string names for pollutants stored in vectors, coordinated with names used in Pollutants.csv and HydroPlusConfig.xml removals
	string Name_Load_Catchment_Pollutant_Median_kg, Name_Load_Catchment_Pollutant_Mean_kg;

	//If timeStep equals zero then file for writing headers
	if (timeStep == 0) {

		ofstream outfilePollutionLoad(path_out);
		if (!outfilePollutionLoad.good()) {
			cout << "Warning: Output folder does not exist or an output file in that folder is open and cannot be overwritten." << endl;
			cout << "Aborting: This warning triggers the HydroPlus simulation to abort." << endl;
			cout << "Correction: Confirm the HydroPlusConfig.xml parameter OutputFolder_Path and files in that folder are closed." << endl;
			//Call abort function, which ends the HydroPlus.exe simulation
			abort();
		}

		//utfilePollutionLoad receives header terms date and time
		outfilePollutionLoad << "YYYYMMDD" << "," << "Hr:Min:Sec";

		//For Loop through pollutant names to write output file header; length of For Loop is Pollutant_Name.size()
		for (int pollutant_ID = 0; pollutant_ID < input->Pollutant_Name.size(); pollutant_ID++) {
			//Create string to represent variable associated with Pollutant_Name
			Name_Load_Catchment_Pollutant_Median_kg = input->Pollutant_Name[pollutant_ID] + "_Load_Median(kg)";
			Name_Load_Catchment_Pollutant_Mean_kg = input->Pollutant_Name[pollutant_ID] + "_Load_Mean(kg)";
			//outfilePollutionLoad  receives header terms of median and mean pollutant name for each pollutant_ID
			outfilePollutionLoad << "," << Name_Load_Catchment_Pollutant_Median_kg << "," << Name_Load_Catchment_Pollutant_Mean_kg;
		}
		//outfilePollutionLoad has line break at end of for loop
		outfilePollutionLoad << endl;
		//outfilePollutionLoad is closed at end of each time step 
		outfilePollutionLoad.close();
	}

	//ofstream with ios::app to open outfilePollutionLoad for appending
	ofstream outfilePollutionLoad(path_out, ios::app);

	//outfilePollutionLoad file stores date and time values
	outfilePollutionLoad << dateVec.at(timeStep) << "," << timeVec.at(timeStep);

	//For Loop through pollutant names to write output file header; length of For Loop is Pollutant_Name.size()
	for (int pollutant_ID = 0; pollutant_ID < input->Pollutant_Name.size(); pollutant_ID++) {
		//Create string to represent variable associated with Pollutant_Name
		Name_Load_Catchment_Pollutant_Median_kg = "Load_Catchment_" + input->Pollutant_Name[pollutant_ID] + "_Median_kg";
		Name_Load_Catchment_Pollutant_Mean_kg = "Load_Catchment_" + input->Pollutant_Name[pollutant_ID] + "_Mean_kg";
		//Pollutant_Load_Median_kg (kg) will store pollutant median load
		outfilePollutionLoad << "," << input->RepoDict[Name_Load_Catchment_Pollutant_Median_kg] << "," << input->RepoDict[Name_Load_Catchment_Pollutant_Mean_kg];
	}

	//outfilePollutionLoad has line break at end of for loop
	outfilePollutionLoad << endl;
	//outfilePollutionLoad is closed at end of each time step 
	outfilePollutionLoad.close();

}


//WaterQuality_Output::writeLoad_by_EMC_via_GI_TS writes EMC loads processed by GI at each time step
//Note: Pollutant_Name vector used below are from Pollutants.csv, read in Inputs.cpp into vector 
void WaterQuality_Output::writeLoad_by_EMC_via_GI_TS(Inputs* input, int timeStep)
{
	//TimeSeries_Pollutants_kg.csv will hold loads in values of kg
	string path_out = input->SimulationStringParams["OutputFolder_Path"] + "TimeSeries_Budget_Pollutants_GI.csv";
	//dateVec stores SimulationDate_Output_GD as YYYYMMDD
	vector<int> dateVec = input->SimulationDate_Output_GD;
	//timeVec stores SimulationTime_Output_HMS as HH:MM:DD
	vector<string> timeVec = input->SimulationTime_Output_HMS;
	//string names for pollutants stored in vectors, coordinated with names used in Pollutants.csv and HydroPlusConfig.xml removals
	string Name_Load_GI_Inflow_Pollutant_Mean_g, Name_Load_GI_Runoff_Surface_Pollutant_Mean_g, Name_Load_GI_Runoff_Vault_Pollutant_Mean_g, Name_Load_GI_Drainage_VadoseZone_Pollutant_Mean_g;
	string Name_Release_GI_Total_Pollutant_Mean_g;

	//If timeStep equals zero then file for writing headers
	if (timeStep == 0) {

		ofstream outfilePollutionLoadViaGI(path_out);
		if (!outfilePollutionLoadViaGI.good()) {
			cout << "Warning: Output folder does not exist or an output file in that folder is open and cannot be overwritten." << endl;
			cout << "Aborting: This warning triggers the HydroPlus simulation to abort." << endl;
			cout << "Correction: Confirm the HydroPlusConfig.xml parameter OutputFolder_Path and files in that folder are closed." << endl;
			//Call abort function, which ends the HydroPlus.exe simulation
			abort();
		}

		//utfilePollutionLoad receives header terms date and time
		outfilePollutionLoadViaGI << "YYYYMMDD" << "," << "Hr:Min:Sec";

		//For Loop through pollutant names to write output file header; length of For Loop is Pollutant_Name.size()
		for (int pollutant_ID = 0; pollutant_ID < input->Pollutant_Name.size(); pollutant_ID++) {
			//Create string to represent variable associated with Pollutant_Name
			Name_Load_GI_Inflow_Pollutant_Mean_g = "Load_GI_Inflow_" + input->Pollutant_Name[pollutant_ID] + "_Mean_g";
			Name_Load_GI_Runoff_Surface_Pollutant_Mean_g = "Load_GI_Runoff_Surface_" + input->Pollutant_Name[pollutant_ID] + "_Mean_g";
			Name_Load_GI_Runoff_Vault_Pollutant_Mean_g = "Load_GI_Runoff_Vault_" + input->Pollutant_Name[pollutant_ID] + "_Mean_g";
			Name_Load_GI_Drainage_VadoseZone_Pollutant_Mean_g = "Load_GI_Drainage_VadoseZone_" + input->Pollutant_Name[pollutant_ID] + "_Mean_g";
			Name_Release_GI_Total_Pollutant_Mean_g = "Release_GI_Total_" + input->Pollutant_Name[pollutant_ID] + "_Mean_g";

			//outfilePollutionLoadViaGI receives header terms of median and mean pollutant name for each pollutant_ID
			outfilePollutionLoadViaGI << "," << Name_Load_GI_Inflow_Pollutant_Mean_g;
			outfilePollutionLoadViaGI << "," << Name_Load_GI_Runoff_Surface_Pollutant_Mean_g << "," << Name_Load_GI_Runoff_Vault_Pollutant_Mean_g;
			outfilePollutionLoadViaGI << "," << Name_Load_GI_Drainage_VadoseZone_Pollutant_Mean_g << "," << Name_Release_GI_Total_Pollutant_Mean_g;
		}
		//outfilePollutionLoadViaGI has line break at end of for loop
		outfilePollutionLoadViaGI << endl;
		//outfilePollutionLoadViaGI is closed at end of each time step 
		outfilePollutionLoadViaGI.close();
	}

	//ofstream with ios::app to open outfilePollutionLoadViaGI for appending
	ofstream outfilePollutionLoadViaGI(path_out, ios::app);

	//outfilePollutionLoadViaGI file stores date and time values
	outfilePollutionLoadViaGI << dateVec.at(timeStep) << "," << timeVec.at(timeStep);

	//For Loop through pollutant names to write output file header; length of For Loop is Pollutant_Name.size()
	for (int pollutant_ID = 0; pollutant_ID < input->Pollutant_Name.size(); pollutant_ID++) {
		//Create string of variable name within beC->vec_by_key, comprised of flow type label in quotes, Pollutant_Name vector, and "_Mean_g"
		Name_Load_GI_Inflow_Pollutant_Mean_g = "Load_GI_Inflow_" + input->Pollutant_Name[pollutant_ID] + "_Mean_g";
		Name_Load_GI_Runoff_Surface_Pollutant_Mean_g = "Load_GI_Runoff_Surface_" + input->Pollutant_Name[pollutant_ID] + "_Mean_g";
		Name_Load_GI_Runoff_Vault_Pollutant_Mean_g = "Load_GI_Runoff_Vault_" + input->Pollutant_Name[pollutant_ID] + "_Mean_g";
		Name_Load_GI_Drainage_VadoseZone_Pollutant_Mean_g = "Load_GI_Drainage_VadoseZone_" + input->Pollutant_Name[pollutant_ID] + "_Mean_g";
		Name_Release_GI_Total_Pollutant_Mean_g = "Release_GI_Total_" + input->Pollutant_Name[pollutant_ID] + "_Mean_g";

		//outfilePollutionLoadViaGI receives header terms of median and mean pollutant name for each pollutant_ID
		outfilePollutionLoadViaGI << "," << input->RepoDict[Name_Load_GI_Inflow_Pollutant_Mean_g];
		outfilePollutionLoadViaGI << "," << input->RepoDict[Name_Load_GI_Runoff_Surface_Pollutant_Mean_g] << "," << input->RepoDict[Name_Load_GI_Runoff_Vault_Pollutant_Mean_g];
		outfilePollutionLoadViaGI << "," << input->RepoDict[Name_Load_GI_Drainage_VadoseZone_Pollutant_Mean_g] << "," << input->RepoDict[Name_Release_GI_Total_Pollutant_Mean_g];
	}

	//outfilePollutionLoadViaGI has line break at end of for loop
	outfilePollutionLoadViaGI << endl;
	//outfilePollutionLoadViaGI is closed at end of each time step 
	outfilePollutionLoadViaGI.close();

}

//WaterQuality_Output::writeLoad_by_EMC_via_GI_Sum writes EMC loads through GI device as sum for simulation
//Note: Pollutant_Name vector used below are from Pollutants.csv, read in Inputs.cpp into vector 
void WaterQuality_Output::writeLoad_by_EMC_via_GI_Sum(Inputs* input)
{
	string Name_Removal_Rate_Pollutant_frac;
	//GI processed catchment totals for all time steps
	string Name_Load_GI_Inflow_Pollutant_Mean_Sum_kg, Name_Load_GI_Runoff_Surface_Pollutant_Mean_Sum_kg, Name_Load_GI_Runoff_Vault_Pollutant_Mean_Sum_kg, Name_Load_GI_Drainage_VadoseZone_Pollutant_Mean_Sum_kg;
	string Name_Release_GI_Total_Pollutant_Mean_Sum_kg;

	ofstream outfilePollutionLoadViaGI_Sum(input->SimulationStringParams["OutputFolder_Path"] + "Summary_Pollutant_Treatment_GI.csv");
	if (!outfilePollutionLoadViaGI_Sum.good()) {
		cout << "Warning: Output folder does not exist or an output file in that folder is open and cannot be overwritten." << endl;
		cout << "Aborting: This warning triggers the HydroPlus simulation to abort." << endl;
		cout << "Correction: Confirm the HydroPlusConfig.xml parameter OutputFolder_Path and files in that folder are closed." << endl;
		//Call abort function, which ends the HydroPlus.exe simulation
		abort();
	}
	outfilePollutionLoadViaGI_Sum.setf(ios::fixed);
	outfilePollutionLoadViaGI_Sum.setf(ios::showpoint);

	//outfilePollutionLoadViaGI_Sum receives header
	outfilePollutionLoadViaGI_Sum << "Pollutant,GI_Removal_Rate_(%),Inflow_Concentration_(mgL),Outflow_Concentration_(mg/L),Inflow_Load_(kg),";
	outfilePollutionLoadViaGI_Sum << "Runoff_Surface_Volume_(m^3),Runoff_Surface_Load_(kg),Runoff_Vault_Drain_Volume_(m^3),Runoff_Vault_Drain_Load_(kg),";
	outfilePollutionLoadViaGI_Sum << "Drainage_VadoseZone_Volume_(m^3),Drainage_VadoseZone_Load_(kg),Total_GI_Pollutant_Release_(kg)" << endl;

	//For Loop through pollutant names to write output file header; length of For Loop is Pollutant_Name.size()
	for (int pollutant_ID = 0; pollutant_ID < input->Pollutant_Name.size(); pollutant_ID++) {
		//Name_Removal_Rate_Pollutant_frac is string name for input->RepoDict variable containing the catchment average removal rate
		Name_Removal_Rate_Pollutant_frac = "Removal_Rate_" + input->Pollutant_Name[pollutant_ID] + "_Avg_frac";
		//Create string of variable name within beC->vec_by_key, comprised of flow type label in quotes, Pollutant_Name vector, and "_Mean_Sum_kg"
		Name_Load_GI_Inflow_Pollutant_Mean_Sum_kg = "Load_GI_Inflow_" + input->Pollutant_Name[pollutant_ID] + "_Mean_Sum_kg";
		Name_Load_GI_Runoff_Surface_Pollutant_Mean_Sum_kg = "Load_GI_Runoff_Surface_" + input->Pollutant_Name[pollutant_ID] + "_Mean_Sum_kg";
		Name_Load_GI_Runoff_Vault_Pollutant_Mean_Sum_kg = "Load_GI_Runoff_Vault_" + input->Pollutant_Name[pollutant_ID] + "_Mean_Sum_kg";
		Name_Load_GI_Drainage_VadoseZone_Pollutant_Mean_Sum_kg = "Load_GI_Drainage_VadoseZone_" + input->Pollutant_Name[pollutant_ID] + "_Mean_Sum_kg";
		Name_Release_GI_Total_Pollutant_Mean_Sum_kg = "Release_GI_Total_" + input->Pollutant_Name[pollutant_ID] + "_Mean_Sum_kg";

		outfilePollutionLoadViaGI_Sum.precision(3);
		//outfilePollutionLoadViaGI_Sum receives Pollutnat_Name
		outfilePollutionLoadViaGI_Sum << input->Pollutant_Name[pollutant_ID] << ",";
		//outfilePollutionLoadViaGI_Sum receives Removal Rate as percent
		outfilePollutionLoadViaGI_Sum << input->RepoDict[Name_Removal_Rate_Pollutant_frac] * 100 << ",";
		//outfilePollutionLoadViaGI_Sum receives Inflow mean concentration (mg/L)
		outfilePollutionLoadViaGI_Sum << input->Pollutant_ConcentrationMean_mg_p_L[pollutant_ID] << ",";
		//outfilePollutionLoadViaGI_Sum receives Outflow mean concentration (mg/L)
		outfilePollutionLoadViaGI_Sum << input->Pollutant_ConcentrationMean_mg_p_L[pollutant_ID] * (1 - input->RepoDict[Name_Removal_Rate_Pollutant_frac]) << ",";
		outfilePollutionLoadViaGI_Sum.precision(2);
		//outfilePollutionLoadViaGI_Sum receives Inflow mean load (kg)
		outfilePollutionLoadViaGI_Sum << input->RepoDict[Name_Load_GI_Inflow_Pollutant_Mean_Sum_kg] << ",";
		//outfilePollutionLoadViaGI_Sum receives GI_Total_RunoffSurface_m3 which is Runoff Surface volume (m3)
		outfilePollutionLoadViaGI_Sum << input->RepoDict["GI_Runoff_Surface_Sum_m3"] << ",";
		//outfilePollutionLoadViaGI_Sum receives Runoff Surface load (kg)
		outfilePollutionLoadViaGI_Sum << input->RepoDict[Name_Load_GI_Runoff_Surface_Pollutant_Mean_Sum_kg] << ",";
		//outfilePollutionLoadViaGI_Sum receives GI_Total_RunoffVaultDrain_m3 which is Runoff Vault Drainpipe volume (m3)
		outfilePollutionLoadViaGI_Sum << input->RepoDict["GI_Runoff_VaultDrain_Sum_m3"] << ",";
		//outfilePollutionLoadViaGI_Sum receives Runoff Vault Drainpipe load (kg)
		outfilePollutionLoadViaGI_Sum << input->RepoDict[Name_Load_GI_Runoff_Vault_Pollutant_Mean_Sum_kg] << ",";
		//outfilePollutionLoadViaGI_Sum receives GI_Total_DrainageVadoseZone_m3 which is Drainage_VadoseZone as volume (m3)
		outfilePollutionLoadViaGI_Sum << input->RepoDict["GI_Drainage_VadoseZone_Sum_m3"] << ",";
		//outfilePollutionLoadViaGI_Sum receives Drainage_VadoseZone load (kg)
		outfilePollutionLoadViaGI_Sum << input->RepoDict[Name_Load_GI_Drainage_VadoseZone_Pollutant_Mean_Sum_kg] << ",";
		//outfilePollutionLoadViaGI_Sum receives Outflow mean release load (kg)
		outfilePollutionLoadViaGI_Sum << input->RepoDict[Name_Release_GI_Total_Pollutant_Mean_Sum_kg] << ",";
		outfilePollutionLoadViaGI_Sum << endl;
	}
	outfilePollutionLoadViaGI_Sum.close();
}


//WaterQuality_Output::writeLoad_Pollutant_Sum writes EMC loads as sum for simulation
//Note: Pollutant_Name vector used below are from Pollutants.csv, read in Inputs.cpp into vector 
void WaterQuality_Output::writeLoad_Pollutant_Sum(Inputs* input)
{
	//Create output file for summary of catchment water balance
	string path_dat = input->SimulationStringParams["OutputFolder_Path"] + "Summary_Budget_WaterQualityLoad.dat";
	string path_csv = input->SimulationStringParams["OutputFolder_Path"] + "Summary_Budget_WaterQualityLoad.csv";
	
	// Turn off .dat output (keep code but comment out)
	/*ofstream WaterQualityEMC_Budget(path_dat);
	if (!WaterQualityEMC_Budget) {
		cout << "Warning: Output folder does not exist or an output file in that folder is open and cannot be overwritten." << endl;
		cout << "Aborting: This warning triggers the HydroPlus simulation to abort." << endl;
		cout << "Correction: Confirm the HydroPlusConfig.xml parameter OutputFolder_Path and files in that folder are closed." << endl;
		//Call abort function, which ends the HydroPlus.exe simulation
		abort();
	}
	WaterQualityEMC_Budget.setf(ios::fixed);
	WaterQualityEMC_Budget.setf(ios::showpoint);
	*/

	ofstream WaterQualityEMC_Budget_CSV(path_csv);
	if (!WaterQualityEMC_Budget_CSV) {
		cout << "Warning: Output folder does not exist or an output file in that folder is open and cannot be overwritten." << endl;
		cout << "Aborting: This warning triggers the HydroPlus simulation to abort." << endl;
		cout << "Correction: Confirm the HydroPlusConfig.xml parameter OutputFolder_Path and files in that folder are closed." << endl;
		//Call abort function, which ends the HydroPlus.exe simulation
		abort();
	}

	
	//string names for pollutants stored in vectors, coordinated with names used in Pollutants.csv and HydroPlusConfig.xml removals
	//catchment loads
	string Name_Load_Catchment_Pollutant_Median_Sum_kg, Name_Load_Catchment_Pollutant_Mean_Sum_kg;
	//GI processed catchment totals for all time steps
	string Name_Load_GI_Inflow_Pollutant_Mean_Sum_kg, Name_Load_GI_Runoff_Surface_Pollutant_Mean_Sum_kg, Name_Load_GI_Runoff_Vault_Pollutant_Mean_Sum_kg, Name_Load_GI_Drainage_VadoseZone_Pollutant_Mean_Sum_kg;
	string Name_Release_GI_Total_Pollutant_Mean_Sum_kg;

	//Note: Use catchment area not folder area fractions. Catchment area fractions computed in AggregateOutput.cpp
	//PC_frac is pervious cover fraction of catchment area
	double PC_frac = input->RepoDict["Catchment_TotalPerviousCover_frac"];
	//IC_frac is impervious cover fraction of catchment area
	double IC_frac = input->RepoDict["Catchment_TotalImperviousCover_frac"];
	//TC_frac is tree cover fraction of catchment area
	double TC_frac = input->RepoDict["Catchment_TotalTreeCover_frac"];
	//TC_overPC_frac is tree cover over pervious cover fraction of catchment area
	double TC_overPC_frac = input->RepoDict["Catchment_TreeCanopyCover_overPervious_frac"];
	//TC_overIC_frac is tree cover over impervious cover fraction of catchment area
	double TC_overIC_frac = input->RepoDict["Catchment_TreeCanopyCover_overImpervious_frac"];
	//IC_noTC_frac is impervious cover not under tree cover fraction of catchment area
	double IC_noTC_frac = input->RepoDict["Catchment_ImperviousCover_noTreeCanopy_frac"];
	//Water_noTC_frac is water cover not under tree cover fraction of catchment area
	double WaterC_noTC_frac = input->RepoDict["Catchment_WaterCover_noTreeCanopy_frac"];
	//SVeg_noTC_frac is short vegetation cover not under tree cover fraction of catchment area
	double SVegC_noTC_frac = input->RepoDict["Catchment_ShortVegCover_noTreeCanopy_frac"];
	//Soil_noTC_frac is soil cover not under tree cover fraction of catchment area
	double SoilC_noTC_frac = input->RepoDict["Catchment_SoilCover_noTreeCanopy_frac"];
	//PermeablePavementC_noTC_frac is permeable pavement cover not under tree cover fraction of catchment area
	double PermeablePavementC_noTC_frac = input->RepoDict["Catchment_PermeablePavementCover_noTreeCanopy_frac"];
	//DCIA_frac is directly connected impervious cover fraction of impervious area
	double DCIA_frac = input->RepoDict["Catchment_DCIA_frac"];
	//InfilExSim_frac is infiltration excess governed area fraction of catchment area
	double InfilExSim_frac = input->RepoDict["Catchment_InfiltExcessGovernedArea_frac"];
	//Macropore_frac is macropore fraction of catchment area
	double MacroPore_frac = input->RepoDict["Catchment_MacroPore_frac"];

	// -----------------------------
	// Turn off. Write the original .dat file
	// -----------------------------
	/*WaterQualityEMC_Budget << " --------------------------------------------------------------------------------------------------" << endl;
	WaterQualityEMC_Budget << "Model Variable (units are _fraction or _kg):                " << "     Value:" << endl;
	WaterQualityEMC_Budget << " --------------------------------------------------------------------------------------------------" << endl;
	//precision function sets precision to 3 decimal places for fractions
	WaterQualityEMC_Budget.precision(3);
	WaterQualityEMC_Budget << "Area_ImperviousAll_frac" << setw(70 - size("Area_ImperviousAll_frac")) << IC_frac << endl;
	WaterQualityEMC_Budget << "Area_PerviousAll_frac" << setw(70 - size("Area_PerviousAll_frac")) << PC_frac << endl;
	WaterQualityEMC_Budget << "Area_TreeOverImpervious_frac" << setw(70 - size("Area_TreeOverImpervious_frac")) << TC_overIC_frac << endl;
	WaterQualityEMC_Budget << "Area_TreeOverPervious_frac" << setw(70 - size("Area_TreeOverPervious_frac")) << TC_overPC_frac << endl;
	WaterQualityEMC_Budget << "Area_ShortVegCanopy_frac" << setw(70 - size("Area_ShortVegCanopy_frac")) << SVegC_noTC_frac << endl;
	WaterQualityEMC_Budget << "Area_SoilNoCanopy_frac" << setw(70 - size("Area_SoilNoCanopy_frac")) << SoilC_noTC_frac << endl;
	WaterQualityEMC_Budget << "Area_PermeablePavementNoCanopy_frac" << setw(70 - size("Area_PermeablePavementNoCanopy_frac")) << PermeablePavementC_noTC_frac << endl;
	WaterQualityEMC_Budget << "Area_WaterNoCanopy_frac" << setw(70 - size("Area_WaterNoCanopy_frac")) << WaterC_noTC_frac << endl;
	WaterQualityEMC_Budget << "Area_DCIA_frac" << setw(70 - size("Area_DCIA_frac")) << DCIA_frac << endl;
	WaterQualityEMC_Budget << "Area_InfiltExcessGoverned_frac" << setw(70 - size("Area_InfiltExcessGoverned_frac")) << InfilExSim_frac << endl;
	WaterQualityEMC_Budget << "Area_MacroPore_frac" << setw(70 - size("Area_MacroPore_frac")) << MacroPore_frac << endl;
	//Note: input->RepoVecDict["Groundwater_surficial_TS_last_frac"][0] is BulkArea value, with Folder_Type_ID = 0 for BulkArea
	WaterQualityEMC_Budget << "TS_First_SurficialGroundwater_frac" << setw(70 - size("TS_first_SurficialGroundwater_frac")) << input->RepoVecDict["Groundwater_surficial_TS_first_frac"][0] << endl;
	WaterQualityEMC_Budget << "TS_Last_SurficialGroundwater_frac" << setw(70 - size("TS_Last_SurficialGroundwater_frac")) << input->RepoVecDict["Groundwater_surficial_TS_last_frac"][0] << endl;
	//precision function sets precision to 2 decimal places for depths
	WaterQualityEMC_Budget.precision(6);
	//For Loop through pollutant names to create string with variable name; length of For Loop is Pollutant_Name.size()
	for (int pollutant_ID = 0; pollutant_ID < input->Pollutant_Name.size(); pollutant_ID++) {
		//Create string of variable name for median and mean pollutant name, reporting load in units kg
		Name_Load_Catchment_Pollutant_Median_Sum_kg = "Load_Catchment_" + input->Pollutant_Name[pollutant_ID] + "_Median_Sum_kg";
		Name_Load_Catchment_Pollutant_Mean_Sum_kg = "Load_Catchment_" + input->Pollutant_Name[pollutant_ID] + "_Mean_Sum_kg";
		//Pollutant_Load_Median_kg (kg) stores pollutant median load
		WaterQualityEMC_Budget << Name_Load_Catchment_Pollutant_Median_Sum_kg << setw(68 - size(Name_Load_Catchment_Pollutant_Median_Sum_kg)) << input->RepoDict[Name_Load_Catchment_Pollutant_Median_Sum_kg] << endl;
		//Pollutant_Load_Mean_kg (kg) stores pollutant mean load
		WaterQualityEMC_Budget << Name_Load_Catchment_Pollutant_Mean_Sum_kg << setw(68 - size(Name_Load_Catchment_Pollutant_Mean_Sum_kg)) << input->RepoDict[Name_Load_Catchment_Pollutant_Mean_Sum_kg] << endl;

		//Create string of variable name within beC->vec_by_key, comprised of flow type label in quotes, Pollutant_Name vector, and "_Mean_Sum_kg"
		Name_Load_GI_Inflow_Pollutant_Mean_Sum_kg = "Load_GI_Inflow_" + input->Pollutant_Name[pollutant_ID] + "_Mean_Sum_kg";
		Name_Load_GI_Runoff_Surface_Pollutant_Mean_Sum_kg = "Load_GI_Runoff_Surface_" + input->Pollutant_Name[pollutant_ID] + "_Mean_Sum_kg";
		Name_Load_GI_Runoff_Vault_Pollutant_Mean_Sum_kg = "Load_GI_Runoff_Vault_" + input->Pollutant_Name[pollutant_ID] + "_Mean_Sum_kg";
		Name_Load_GI_Drainage_VadoseZone_Pollutant_Mean_Sum_kg = "Load_GI_Drainage_VadoseZone_" + input->Pollutant_Name[pollutant_ID] + "_Mean_Sum_kg";
		Name_Release_GI_Total_Pollutant_Mean_Sum_kg = "Release_GI_Total_" + input->Pollutant_Name[pollutant_ID] + "_Mean_Sum_kg";
		//Name_Load_GI_Inflow_Pollutant_Mean_Sum_kg (kg) store pollutant mean load
		WaterQualityEMC_Budget << Name_Load_GI_Inflow_Pollutant_Mean_Sum_kg << setw(68 - size(Name_Load_GI_Inflow_Pollutant_Mean_Sum_kg)) << input->RepoDict[Name_Load_GI_Inflow_Pollutant_Mean_Sum_kg] << endl;
		WaterQualityEMC_Budget << Name_Load_GI_Runoff_Surface_Pollutant_Mean_Sum_kg << setw(68 - size(Name_Load_GI_Runoff_Surface_Pollutant_Mean_Sum_kg)) << input->RepoDict[Name_Load_GI_Runoff_Surface_Pollutant_Mean_Sum_kg] << endl;
		WaterQualityEMC_Budget << Name_Load_GI_Runoff_Vault_Pollutant_Mean_Sum_kg << setw(68 - size(Name_Load_GI_Runoff_Vault_Pollutant_Mean_Sum_kg)) << input->RepoDict[Name_Load_GI_Runoff_Vault_Pollutant_Mean_Sum_kg] << endl;
		WaterQualityEMC_Budget << Name_Load_GI_Drainage_VadoseZone_Pollutant_Mean_Sum_kg << setw(68 - size(Name_Load_GI_Drainage_VadoseZone_Pollutant_Mean_Sum_kg)) << input->RepoDict[Name_Load_GI_Drainage_VadoseZone_Pollutant_Mean_Sum_kg] << endl;
		WaterQualityEMC_Budget << Name_Release_GI_Total_Pollutant_Mean_Sum_kg << setw(68 - size(Name_Release_GI_Total_Pollutant_Mean_Sum_kg)) << input->RepoDict[Name_Release_GI_Total_Pollutant_Mean_Sum_kg] << endl;
	}
	*/

	// -----------------------------
	// Write the new .csv file
	// -----------------------------
	WaterQualityEMC_Budget_CSV.setf(ios::fixed);
	WaterQualityEMC_Budget_CSV.precision(6);

	// Title block
	WaterQualityEMC_Budget_CSV << "-------------------------------------------------------------------------------------\n";
	WaterQualityEMC_Budget_CSV << "Model_Variable,Value,Units\n";
	WaterQualityEMC_Budget_CSV << "-------------------------------------------------------------------------------------\n";

	// Area fractions and groundwater state
	WaterQualityEMC_Budget_CSV << "Area_ImperviousAll_frac," << IC_frac << ",frac\n";
	WaterQualityEMC_Budget_CSV << "Area_PerviousAll_frac," << PC_frac << ",frac\n";
	WaterQualityEMC_Budget_CSV << "Area_TreeOverImpervious_frac," << TC_overIC_frac << ",frac\n";
	WaterQualityEMC_Budget_CSV << "Area_TreeOverPervious_frac," << TC_overPC_frac << ",frac\n";
	WaterQualityEMC_Budget_CSV << "Area_ShortVegCanopy_frac," << SVegC_noTC_frac << ",frac\n";
	WaterQualityEMC_Budget_CSV << "Area_SoilNoCanopy_frac," << SoilC_noTC_frac << ",frac\n";
	WaterQualityEMC_Budget_CSV << "Area_PermeablePavementNoCanopy_frac," << PermeablePavementC_noTC_frac << ",frac\n";
	WaterQualityEMC_Budget_CSV << "Area_WaterNoCanopy_frac," << WaterC_noTC_frac << ",frac\n";
	WaterQualityEMC_Budget_CSV << "Area_DCIA_frac," << DCIA_frac << ",frac\n";
	WaterQualityEMC_Budget_CSV << "Area_InfiltExcessGoverned_frac," << InfilExSim_frac << ",frac\n";
	WaterQualityEMC_Budget_CSV << "Area_MacroPore_frac," << MacroPore_frac << ",frac\n";
	WaterQualityEMC_Budget_CSV << "TS_First_SurficialGroundwater_frac," << input->RepoVecDict["Groundwater_surficial_TS_first_frac"][0] << ",frac\n";
	WaterQualityEMC_Budget_CSV << "TS_Last_SurficialGroundwater_frac," << input->RepoVecDict["Groundwater_surficial_TS_last_frac"][0] << ",frac\n";

	// Pollutant loop
	for (int pollutant_ID = 0; pollutant_ID < input->Pollutant_Name.size(); pollutant_ID++) {
		const string& P = input->Pollutant_Name[pollutant_ID];

		string Name_Load_Catchment_Pollutant_Median_Sum_kg = "Load_Catchment_" + P + "_Median_Sum_kg";
		string Name_Load_Catchment_Pollutant_Mean_Sum_kg = "Load_Catchment_" + P + "_Mean_Sum_kg";
		string Name_Load_GI_Inflow_Pollutant_Mean_Sum_kg = "Load_GI_Inflow_" + P + "_Mean_Sum_kg";
		string Name_Load_GI_Runoff_Surface_Pollutant_Mean_Sum_kg = "Load_GI_Runoff_Surface_" + P + "_Mean_Sum_kg";
		string Name_Load_GI_Runoff_Vault_Pollutant_Mean_Sum_kg = "Load_GI_Runoff_Vault_" + P + "_Mean_Sum_kg";
		string Name_Load_GI_Drainage_VadoseZone_Pollutant_Mean_Sum_kg =
			"Load_GI_Drainage_VadoseZone_" + P + "_Mean_Sum_kg";
		string Name_Release_GI_Total_Pollutant_Mean_Sum_kg = "Release_GI_Total_" + P + "_Mean_Sum_kg";

		WaterQualityEMC_Budget_CSV << Name_Load_Catchment_Pollutant_Median_Sum_kg << ","
			<< input->RepoDict[Name_Load_Catchment_Pollutant_Median_Sum_kg] << ",kg\n";
		WaterQualityEMC_Budget_CSV << Name_Load_Catchment_Pollutant_Mean_Sum_kg << ","
			<< input->RepoDict[Name_Load_Catchment_Pollutant_Mean_Sum_kg] << ",kg\n";
		WaterQualityEMC_Budget_CSV << Name_Load_GI_Inflow_Pollutant_Mean_Sum_kg << ","
			<< input->RepoDict[Name_Load_GI_Inflow_Pollutant_Mean_Sum_kg] << ",kg\n";
		WaterQualityEMC_Budget_CSV << Name_Load_GI_Runoff_Surface_Pollutant_Mean_Sum_kg << ","
			<< input->RepoDict[Name_Load_GI_Runoff_Surface_Pollutant_Mean_Sum_kg] << ",kg\n";
		WaterQualityEMC_Budget_CSV << Name_Load_GI_Runoff_Vault_Pollutant_Mean_Sum_kg << ","
			<< input->RepoDict[Name_Load_GI_Runoff_Vault_Pollutant_Mean_Sum_kg] << ",kg\n";
		WaterQualityEMC_Budget_CSV << Name_Load_GI_Drainage_VadoseZone_Pollutant_Mean_Sum_kg << ","
			<< input->RepoDict[Name_Load_GI_Drainage_VadoseZone_Pollutant_Mean_Sum_kg] << ",kg\n";
		WaterQualityEMC_Budget_CSV << Name_Release_GI_Total_Pollutant_Mean_Sum_kg << ","
			<< input->RepoDict[Name_Release_GI_Total_Pollutant_Mean_Sum_kg] << ",kg\n";
	}


}

//writeLoad_BufferDynamic function writes loads from the Buffer Dynamic model using export coefficient (EC) values
void WaterQuality_Output::writeLoad_BufferDynamic(const vector<double>& result, const vector<double>& Year, Inputs* input, const string& pollutant)
{
	ofstream outfile(input->SimulationStringParams["OutputFolder_Path"] + "AverageYearLoad_" + pollutant + ".csv");
	if (!outfile.good()) {
		cout << "Warning: Output folder does not exist or an output file in that folder is open and cannot be overwritten." << endl;
		cout << "Aborting: This warning triggers the HydroPlus simulation to abort." << endl;
		cout << "Correction: Confirm the HydroPlusConfig.xml parameter OutputFolder_Path and files in that folder are closed." << endl;
		//Call abort function, which ends the HydroPlus.exe simulation
		abort();
	}

	//precision(0) for Area (m^2) and Pixel Lenght (m)
	outfile.precision(0);
	outfile << fixed;
	outfile << "River_Basin_Area" << "," << input->cell_count * Inputs::Length_Pixel_Side_m * Inputs::Length_Pixel_Side_m << "," << "m^2" << endl;
	outfile << "NLCD_Map_Pixel_Length" << "," << Inputs::Length_Pixel_Side_m << "," << "m" << endl;
	outfile << "NLCD_Class" << "," << "LC11" << "," << "LC21" << "," << "LC22" << "," << "LC23" << "," << "LC24" << "," << "LC31" << ","
		<< "LC41" << "," << "LC42" << "," << "LC43" << "," << "LC52" << "," << "LC71" << "," << "LC81" << "," << "LC82" << "," << "LC90" << "," << "LC95" << endl;

	outfile << "NLCD_Count_per_Class" << ",";

	outfile << input->LC11 << ","<< input->LC21 << "," << input->LC22 << "," << input->LC23 << "," << input->LC24 << "," << input->LC31 << ","
		<< input->LC41 << "," << input->LC42 << "," << input->LC43 << "," << input->LC52 << ","
		<< input->LC71 << "," << input->LC81 << "," << input->LC82 << "," << input->LC90 << "," << input->LC95;
	outfile << endl;
	outfile << endl;


	outfile << "Year"
		<< "," << "Predicted_Load_" + pollutant
		<< "," << "Unit"
		<< endl;

	//Note: Load in kg, with precision(4) equivalent to miligram precision
	outfile.precision(4);
	outfile.setf(ios::showpoint);
	auto Load__kg = result.begin();
	for (auto year_it = Year.begin(); year_it != Year.end(); ++year_it) {

		outfile << static_cast<int>(*year_it)
			<< "," << *Load__kg
			<< "," << "kg"
			<< endl;
		Load__kg++;
	}
	outfile.close();
}

void WaterQuality_Output::writeLoad_BufferDynamic_extended(vector <pair<string, vector<double>>>&result_map, Inputs* input, const string& pollutant) {
	ofstream outfile(input->SimulationStringParams["OutputFolder_Path"] + "DailyLoad_" + pollutant + ".csv");
	if (!outfile.good()) {
		cout << "Warning: Output folder does not exist or an output file in that folder is open and cannot be overwritten." << endl;
		cout << "Aborting: This warning triggers the HydroPlus simulation to abort." << endl;
		cout << "Correction: Confirm the HydroPlusConfig.xml parameter OutputFolder_Path and files in that folder are closed." << endl;
		//Call abort function, which ends the HydroPlus.exe simulation
		abort();
	}
	//write the header line, date and load column name
	for (auto it = result_map.begin(); it != result_map.end(); it++) {
		outfile << it->first;
		outfile << ",";
	}
	outfile << endl;

	outfile.precision(4);
	outfile.setf(ios::showpoint);
	//time step is equal to the size of the value of each map pair
	int timestep = size(result_map.begin()->second);
	
	for (int i = 0; i < timestep; i++) {//loop through each time step
		//following columns are writing out the modeling results
		for (auto it = result_map.begin(); it != result_map.end(); it++) {//loop through each parameter
			vector<double> vector_temp = it->second;
			outfile << vector_temp[i];
			outfile << ",";
		}
		outfile << endl;
	}
	
}