/***************************************************************************
Student name:
Course Code:
*******************************************************************************/
#include <iostream>
#include <fstream>
#include <sstream>
#include <bits/stdc++.h>
#include <string>
#include <cstdlib>
using namespace std;
/***************************************************************************
Functions declarations 
*******************************************************************************/
bool FileValid(string);
bool IsValidPLU(string);
bool IsValidName(string);
bool IsValidType(string);
bool IsValidPrice(string);
bool IsValidInventory(string);
string tokenize(string &);
int getWordsCount(string);

/***************************************************************************
Main Class of the  program, Execution 

*******************************************************************************/
int main() {

    string fName;
    cout << "input file: "; // input the file
    cin >> fName;

    cout << "Checking " << fName << "*****" << endl;

    if (FileValid(fName))
        cout << endl << fName << " Valid content " << endl; // validation if the file content is valid
    else
        cout << endl << fName << " Invalid file, upload another file " << endl; // validation of the file content to be invalid

    return 0;
}

bool FileValid(string fName) {

    ifstream myfile(fName.c_str());

    string line;
    string token;

    if (myfile.is_open()) {

        while (getline(myfile, line)) {
            cout << endl;

            int i = 1;
            int c = getWordsCount(line); // get the total word count of the file

            while (line.length() != 0 && i < c+2) {
                token = tokenize(line);

                if (i == 1) {
                    if (IsValidPLU(token)) {
                    cout << "Token #1 is " << token << ", Valid PLU" << endl; // check if the PLU is valid
                    } else {
                    cout << "Token #1 is " << token << ", Invalid PLU" << endl; // checks if the PLU is invalid
                    return false;
                    }

                } else if (i == 2) {
                    if (IsValidName(token)) {
                    cout << "Token #2 is " << token << ", Valid product name" << endl; // checks whether the product name is valid
                    } else {
                    cout << "Token #2 is " << token << ", Invalid product name " << endl; // checks whether the product name is invalid
                    return false;
                    }

                } else if (i == 3) {
                    if (IsValidType(token)) {
                    cout << "Token #3 is " << token << ", Sales type is valid" << endl; // checks whether sales type is valid
                    } else {
                    cout << "Token #3 is " << token << ", Sales type is invalid" << endl; // checks whether sales type is invalid
                    return false;
                    }

                } else if (i == 4) {
                    if (IsValidPrice(token)) {
                    cout << "Token #4 is " << token << ", Price is valid" << endl; // checks whether price is valid
                    } else {
                    cout << "Token #4 is " << token << ", Price is invalid" << endl; // checks whether price is invalid and returns false
                    return false;
                    }

                } else if (i == 5) {
                    if (IsValidInventory(token)) {
                    cout << "Token #5 is " << token << ", Inventory is valid" << endl; // checks the file inventory is valid
                    } else {
                    cout << "Token #5 is " << token << ", Inventory is invalid" << endl; // checks the file inventory is invalid and return false
                    return false;
                    }

                } else if (i == 6 && !token.empty()) {
                    cout << "Token #6 is " << token << ", Too many items in record" << endl; // cautions on the item record exceeds the number declared 
                    return false;
                }

                i++;
            }
        }
    } else {
        cout << "Unable to open the file!!!" << endl;
    } 
    return true;
}

string tokenize(string &line) {
    std::string delimiter = " ";
    size_t pos = 0;
    std::string token = "";

    while(!line.empty() && line.at(0) == ' ') {
        line.erase(0, 1);
    }

    if ((pos = line.find(delimiter)) != std::string::npos) {
        token = line.substr(0, pos);
        line.erase(0, pos + delimiter.length());
    }

    if(token == "") {
        token = line;
        line = "";
    }
    return token;
}

bool IsValidPLU(string str) { // execute a valid PLU file
    bool st = false;

    if (str.length() != 4) {
        return false;
    } else {
        for (size_t i = 0; i < str.length(); i++) {

            char ch = str[i];

            if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) {
            st = true;
            } else if (ch >= '0' && ch <= '9') {
            st = true;
            } else {
            return false;
            }

        }
    }

    return st;
}

bool IsValidName(string str) { // execute a valid product name file
    char ch = str[0];

    if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))
        return true;
    else
        return false;
}

bool IsValidType(string str) { // execute a valid sales type file
    if (str.length() == 1 && (str[0] == '0' || str[0] == '1'))
        return true;
    else
        return false;
}

bool IsValidPrice(string str) { // execute a valid price file
    bool st = false;
    int dot = 0;

    for (size_t i = 0; i < str.length(); i++) {
        char ch = str[i];
        if (ch >= '0' && ch <= '9') {
            st = true;
        } else if (ch == '.') {
            dot++;
            if (dot > 1)
                return false;
            else {
                st = true;
                string str2 = str.substr(i, str.length());

                if (str2.length() > 3)
                    return false;
            }
        } else {
            return false;
        }
    }

    return st;
}

bool IsValidInventory(string str) { // execute a valid inventory file
    bool st = true;

    for (size_t i = 0; i < str.length(); i++) {
        char ch = str[i];
        if (ch < '0' || ch > '9') {
            st = false;
        }
    }

    return st;
}

int getWordsCount(string str) { // execute the number of words in the file
    std::stringstream stream(str);

    int length = int(std::distance(std::istream_iterator<std::string>(stream), std::istream_iterator<std::string>()));

    return length;
}
