// Include statements
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <vector>
#include <algorithm>

// Include custom headers
#include "Date.h"

// Declare std namespace
using namespace std;

int main(int argc, char const *argv[]) { // Start main function

    // Enumerated lists to represent command-line arguments in a readable format for error checking and file name population
    enum expectedArguments {PROGRAM_EXECUTABLE, INPUT_FILE, OUTPUT_FILE};

    // Check that the correct number of command-line arguments are present
    if (argc != 3) {
        cout << "ERROR: Program expects three (3) arguments." << endl;
        cout << "Expected format: \"./[PROGRAM_EXECUTABLE].[extension] [INPUT_FILE].[extension] [OUTPUT_FILE].[extension]\"" << endl;
        cout << "Aborting program." << endl;
        exit(-1); // Exit with error code
    }

    // Open input file of specified name (second command-line argument)
    ifstream inputFile;
    inputFile.open(argv[INPUT_FILE]);
    if (!(inputFile.is_open())) { // Error check opening inputFile
        cout << "ERROR: Could not open " << argv[INPUT_FILE] << "." << endl;
        cout << "Aborting program." << endl;
        exit(-1); // Exit with error code
    }

    // Open (or create) output file of specified name (second command-line argument)
    ofstream outputFile;
    outputFile.open(argv[OUTPUT_FILE]);
    if (!(outputFile.is_open())) { // Error check opening outputFile
        cout << "ERROR: Could not open " << argv[OUTPUT_FILE] << "." << endl;
        cout << "Aborting program." << endl;
        exit(-1); // Exit with error code
    }

    // Read the first line from inputFile and store as the number of date entries
    int numEntries;
    inputFile >> numEntries;

    // Create a vector of type Date
    vector<Date> dateEntries;

    // Read each line from inputFile
    string currentLine; // Declare string to be used in getline()
    int count = 0; // Declare and initialize count for error checking
    while (getline(inputFile, currentLine)) { // While getline() does not fail (not end of file)
        if (currentLine.length() > 1) { // If the length of the current line is greater than 1 (not the line indicating numEntries)
            // Declare strings to be updated as lines are parsed
            string monthString;
            string dayString;
            string yearString;

            for (size_t i = 0; i < currentLine.length(); ++i) {
                if (isspace(currentLine.at(i))) {// Check for space in line
                    string newCurrentLine;
                    for (size_t j = i + 1; j < currentLine.length(); ++j) {
                        newCurrentLine = newCurrentLine + currentLine.at(j); // Update newCurrentLine with indexes of currentLine after space is found
                    }
                    currentLine = newCurrentLine; // Set currentLine to the new contents
                    break; // Leave for loop
                } else {
                    monthString = monthString + currentLine.at(i); // Update monthString with indexes of currentLine before next space
                }
            }

            for (size_t i = 0; i < currentLine.length(); ++i) {
                if (isspace(currentLine.at(i))) {// Check for space in line
                    string newCurrentLine;
                    for (size_t j = i + 1; j < currentLine.length(); ++j) {
                        newCurrentLine = newCurrentLine + currentLine.at(j); // Update newCurrentLine with indexes of currentLine after space is found
                    }
                    currentLine = newCurrentLine; // Set currentLine to the new contents
                    break; // Leave for loop
                } else {
                    dayString = dayString + currentLine.at(i); // Update dayString with indexes of currentLine before next space
                }
            }

            for (size_t i = 0; i < currentLine.length(); ++i) {
                if (isspace(currentLine.at(i))) {// Check for space in line
                    string newCurrentLine;
                    for (size_t j = i + 1; j < currentLine.length(); ++j) {
                        newCurrentLine = newCurrentLine + currentLine.at(j); // Update newCurrentLine with indexes of currentLine after space is found
                    }
                    currentLine = newCurrentLine; // Set currentLine to the new contents
                    break; // Leave for loop
                } else {
                    yearString = yearString + currentLine.at(i); // Update yearString with indexes of currentLine before next space
                }
            }

            // Convert strings to integers
            int month = stoi(monthString);
            int day = stoi(dayString);
            int year = stoi(yearString);
            
            // Add instance of Date to dateEntries vector
            dateEntries.push_back(Date(month, day, year));

            count++; // Increment count for successful line read
        }
    }

    // Error check number of lines in inputFile
    if (count != numEntries) {
        cout << "ERROR: Number of lines in " << argv[INPUT_FILE] << " does not equal the expected number of entries (" << numEntries << ")." << endl;
        cout << "Aborting program." << endl;
        exit(-1); // Exit with error code
    }

    // Sort objects in dateEntries
    sort(dateEntries.begin(), dateEntries.end(), Date::compare);

    // Print assembled strings from objects in dateEntries
    for (int i = numEntries - 1; i >= 0; --i) { // Iterating from the end of dateEntries to the start, because the compare function used in sort() starts with year
        outputFile << dateEntries.at(i).print() << endl;
    }

    // Close files
    inputFile.close();
    outputFile.close();

    return 0; // Return end code

}