//MUHAMMAD NAZRI IZZAT BIN HAMDAN A20EC0216 28/1/2021
//RAJA MUHAMMAD HAFIZ BIN RAJA ALAUDIN SHAH A20EC0223

#include <iostream>
#include <string>
#include <fstream>
#include <iomanip>
#include <sstream>

#define NUMBER_OF_ARRAYS_TO_FILL        5

#define TOTAL_RAINFALL_ARRAY_INDEX      0
#define RAIN_DAYS_PER_MONTH_ARRAY_INDEX 1
#define HIGH_TEMERATURE_ARRAY_INDEX     2
#define LOW_TEMPERATURE_ARRAY_INDEX     3
#define MONTH_ARRAY_INDEX               4

using namespace std;

void readFile(double* total_rainfall_array, double* rain_days_per_month_array, double* high_temperature_array, double* low_temperature_array, string* month_array, int arrays_length) {

     // Create a text string, which is used to output the text file
     string myText;
     int counter = 0;

     // Read from the text file
     ifstream MyReadFile("data.txt");

     if (MyReadFile.is_open())
     {
          // Use a while loop together with the getline() function to read the file line by line
          while (getline(MyReadFile, myText))
          {
               //read a line in string and tokkenize it into the arrays
               int counter_for_arrays = 0;
               stringstream ssin(myText);
               while (ssin.good() && counter_for_arrays < NUMBER_OF_ARRAYS_TO_FILL) {

                    if (counter_for_arrays == TOTAL_RAINFALL_ARRAY_INDEX)
                         ssin >> total_rainfall_array[counter];
                    else if (counter_for_arrays == RAIN_DAYS_PER_MONTH_ARRAY_INDEX)
                         ssin >> rain_days_per_month_array[counter];
                    else if (counter_for_arrays == HIGH_TEMERATURE_ARRAY_INDEX)
                         ssin >> high_temperature_array[counter];
                    else if (counter_for_arrays == LOW_TEMPERATURE_ARRAY_INDEX)
                         ssin >> low_temperature_array[counter];
                    else if (counter_for_arrays == MONTH_ARRAY_INDEX)
                         ssin >> month_array[counter];

                    ++counter_for_arrays;
               }

               counter++;
          }

          // Close the file
          MyReadFile.close();
     }

     else cout << "Unable to open file";

     MyReadFile.close();
}

int arrays_Length() {

     // Create a text string, which is used to output the text file
     string myText;
     int count = 0;

     // Read from the text file
     ifstream MyReadFile("data.txt");

     if (MyReadFile.is_open())
     {
          // Use a while loop together with the getline() function to read the file line by line
          while (getline(MyReadFile, myText))
          {
               //read a line and add in count
               //cout << myText << endl;
               count++;
          }

          // Close the file
          MyReadFile.close();
     }

     else cout << "Unable to open file";

     MyReadFile.close();

     return count;
}

void calculateAverageTemperatureArray( double* high_temperature_array, double* low_temperature_array, double* average_temperature_array, int arrays_length) {

     for (int i = 0; i < arrays_length; i++)
          average_temperature_array[i] = (high_temperature_array[i] + low_temperature_array[i]) / 2;

}

double calculateTotalRainfall( double* total_rainfall_array , int arrays_length) {
     double sum = 0.0;

     for (int i = 0; i < arrays_length; i++)
          sum += total_rainfall_array[i];

     return sum;
}

double calculateAverageMonthlyRainfall( double* total_rainfall_array , int arrays_length) {
     double sum = 0.0;

     for (int i = 0; i < arrays_length; i++)
          sum += total_rainfall_array[i];

     return (sum / arrays_length); // return the average
}

double calculateAverageTemperature( double* average_temperature_array , int arrays_length) {
     double sum = 0.0;

     for (int i = 0; i < arrays_length; i++)
          sum += average_temperature_array[i];

     return (sum / arrays_length); // return the average
}

double calculateHighestTemperature( double* high_temperature_array, int* highest_temperature_month_index , int arrays_length) {
     double highest = 0.0;
     highest = high_temperature_array[0]; // initialize with the the first index to compare further

     for (int i = 0; i < arrays_length; i++) {

          if (highest < high_temperature_array[i]) {
               highest = high_temperature_array[i];
               *highest_temperature_month_index = i; // set the index for highest temp
          }

     }

     return highest;
}

double calculateLowestTemperature(double* high_temperature_array, int* highest_temperature_month_index , int arrays_length) {
     double lowest = 0.0;
     lowest = high_temperature_array[0]; // initialize with the the first index to compare further

     for (int i = 0; i < arrays_length; i++) {

          if (lowest > high_temperature_array[i]) {
               lowest = high_temperature_array[i];
               *highest_temperature_month_index = i; // set the index for lowest temp
          }

     }

     return lowest;
}

void printSummary(double* total_rainfall_array, double* rain_days_per_month_array, double* high_temperature_array, double* low_temperature_array, string* month_array, double* average_temperature_array, double total_rainfall, double arrays_length, double average_monthly_rain, double average_yearly_temperature, double highest_temperature, int highest_temperature_month_index, double lowest_temperature, int lowest_temperature_month_index) {

     cout << "Total Rainfall: " << total_rainfall << endl;
     cout << "Average Monthly Rain: " << average_monthly_rain << endl;
     cout << "Average Monthly Rain: " << average_yearly_temperature << endl;
     cout << "Highest Temperature: " << highest_temperature << "  (Month " << highest_temperature_month_index + 1 << ": " << month_array[highest_temperature_month_index] << ")"<< endl;
     cout << "Lowest Temperature: " << lowest_temperature << "  (Month " << lowest_temperature_month_index + 1 << ": " << month_array[lowest_temperature_month_index] << ")" << endl << endl;

     const char separator = ' ';
     const int nameWidth = 12;
     const int numWidth = 8;

     //used setw() to set the width while printing a string.
     //used setprecision() to set the precision for floating values.
     //left (or right) allow you to define the alignment.
     //used setfill() Fill the rest with the character you want (in your case ' ').

     cout << left << setw(nameWidth) << setfill(separator) << "Month";
     cout << left << setw(nameWidth) << setfill(separator) << "Rain";
     cout << left << setw(nameWidth) << setfill(separator) << "Rain days";
     cout << left << setw(nameWidth) << setfill(separator) << "Hi TEMP";
     cout << left << setw(nameWidth) << setfill(separator) << "Lo TEMP";
     cout << left << setw(nameWidth) << setfill(separator) << "Avg TEMP";
     cout << endl ;

     cout << left << setw(nameWidth) << setfill(separator) << "=====";
     cout << left << setw(nameWidth) << setfill(separator) << "====";
     cout << left << setw(nameWidth) << setfill(separator) << "=========";
     cout << left << setw(nameWidth) << setfill(separator) << "=======";
     cout << left << setw(nameWidth) << setfill(separator) << "=======";
     cout << left << setw(nameWidth) << setfill(separator) << "=======";
     cout << endl ;

     for (int i = 0; i < arrays_length; i++) {
          cout << left << setw(nameWidth) << setfill(separator) << setprecision(2)<< month_array[i];
          cout << left << setw(nameWidth) << setfill(separator) << setprecision(5)<< total_rainfall_array[i];
          cout << left << setw(nameWidth) << setfill(separator) << setprecision(3)<< rain_days_per_month_array[i];
          cout << left << setw(nameWidth) << setfill(separator) << setprecision(3)<< high_temperature_array[i];
          cout << left << setw(nameWidth) << setfill(separator) << setprecision(3)<< low_temperature_array[i];
          cout << left << setw(nameWidth) << setfill(separator) << setprecision(3)<< average_temperature_array[i];
          cout << endl;
     }
}
int main()
{
    //It contains the actual number of lines in the file to set the length of the arrays
    int arrays_length = 0;

    //read the file and set the length
    arrays_length = arrays_Length();

    //Total Rainfall
    //Number of rain days per month
    //High Temperature
    //Low Temperature
    //Month Name

    double* total_rainfall_array = new double[arrays_length];
    double* rain_days_per_month_array = new double[arrays_length];
    double* high_temperature_array = new double[arrays_length];
    double* low_temperature_array = new double[arrays_length];
    string* month_array = new string[arrays_length];

    double* average_temperature_array = new double[arrays_length];

    //for printing on the screen
    double total_rainfall = 0.0;
    double average_monthly_rain = 0.0;
    double highest_temperature = 0.0;
    double lowest_temperature = 0.0;
    double average_yearly_temperature = 0.0;

    int highest_temperature_month_index = 0;
    int lowest_temperature_month_index = 0;

    //initialize the arrays with 0.0
    for (int i = 0; i < arrays_length; i++)
    {
         total_rainfall_array[i] = 0.0;
         rain_days_per_month_array[i] = 0.0;
         high_temperature_array[i] = 0.0;
         low_temperature_array[i] = 0.0;
    }

    //read the file and fill the arrays
    readFile(total_rainfall_array, rain_days_per_month_array, high_temperature_array, low_temperature_array, month_array , arrays_length);

    //calculate the average temperature and store in average_temperature_array
    calculateAverageTemperatureArray(high_temperature_array , low_temperature_array , average_temperature_array , arrays_length);

    //return the total  rainfall
    total_rainfall = calculateTotalRainfall(total_rainfall_array , arrays_length);

    //return the average monthly rain
    average_monthly_rain = calculateAverageMonthlyRainfall(total_rainfall_array , arrays_length);

    //returns the average yearly temperature
    average_yearly_temperature = calculateAverageTemperature(average_temperature_array , arrays_length);

    //returns the highest among all the temperatures
    highest_temperature = calculateHighestTemperature(high_temperature_array , &highest_temperature_month_index , arrays_length);

    //returns the highest among all the temperatures
    lowest_temperature = calculateLowestTemperature(low_temperature_array , &lowest_temperature_month_index , arrays_length);

    //print on the screen the desired output
    printSummary(total_rainfall_array, rain_days_per_month_array, high_temperature_array, low_temperature_array, month_array, average_temperature_array, total_rainfall, arrays_length, average_monthly_rain, average_yearly_temperature, highest_temperature, highest_temperature_month_index, lowest_temperature, lowest_temperature_month_index);


    return 0;

}
