/*******************************************************************************************
09b.cpp
    read data into an array of objects, then display them and some calculations
*******************************************************************************************/
#include <iostream>
#include <string>
#include <fstream>

using namespace std;

class item {
    public:
        int part;
        string desc;
        float price;
};

//prototypes
void readDBase(string file, item list[], const int size, int& count);
void readInput(string file, item list[], const int size, int& count);
void XRef(item DB[], const int DBsize, item parts[], const int partsize);
int indexOfMatch(const int part, const item list[], const int listsize);
float subTotal(item [], const int size);
void showList(item [], const int size);

void main() {
    const int MaxDB = 100;
    item DBase[MaxDB];
    int DBcount = 0;

    const int MaxInput = 1000;
    item Input[MaxInput];
    int InCount = 0;

    string filename;
    cout << "Enter the DATABASE FILE to read: ";
    cin >> filename;
    readDBase(filename, DBase, MaxDB, DBcount);
    cout << "Enter the SCANNER FILE to read: ";
    cin >> filename;
    readInput(filename, Input, MaxInput, InCount);
    float taxRate;
    cout << "Enter the tax rate (as a percent): ";
    cin >> taxRate;
    cout << endl;

    // run by the scanner data to see what is a valid item in the order
    XRef(DBase, DBcount, Input, InCount);

    //perform necessary calculations
    float subtotal = subTotal(Input, InCount);
    float tax = subtotal * taxRate/100.0;
    float total = subtotal + tax;

    //display the "invoice"
    showList(Input, InCount);
    cout << "----------------------------------" << endl
         << "Subtotal: $" << subtotal << endl;

    cout.unsetf(ios::fixed);
    cout.precision(6);
    cout << "Tax (" << taxRate;
    cout.setf(ios::fixed);
    cout.precision(2);

    cout << "%): $" << tax << endl
         << "Total: $" << total << endl;

}

// ------- Load the database file from disk and init counters -------
void readDBase(string file, item list[], const int size, int& count) {
    ifstream fin(file.c_str());

    for (int i = 0; i < size; i++) {
        if(fin >> list[i].part >> list[i].desc >> list[i].price)
            count++;
        else
            break;
    }
}

// ------- Load the list of scanned part numbers from disk
void readInput(string file, item list[], const int size, int& count) {
    ifstream fin(file.c_str());

    for (int i = 0; i < size; i++)
        if (fin >> list[i].part)
            count++;
        else
            break;
}

// ------- Cross-reference the list and copy info from the inventory
void XRef(item DB[], const int DBsize, item parts[], const int partsize) {
    for (int i = 0; i < partsize; i++) {
        int index = indexOfMatch(parts[i].part, DB, DBsize);
        if (index > -1) {
            parts[i].desc = DB[index].desc;
            parts[i].price = DB[index].price;
        }
        else
            parts[i].desc = "Not Found";
    }
}

// ------- Return the inventory index position of a given part number
int indexOfMatch(const int part, const item list[], const int listsize) {
    int foundAt = -1;
    for (int i = 0; i < listsize; i++)
        if (list[i].part == part) {
            foundAt = i;
            break;
        }
    return foundAt;
}

// ------- parse the DBase for the subtotal of all items -------
float subTotal(item list[], const int size) {
    float sum = 0.;

    for (int i = 0; i < size; i++)
        sum += list[i].price;

    return sum;
}

// ------- print out the individual items -------
void showList(item list[], const int count) {
    //currency formatting
    cout.setf(ios::fixed);
^Icout.precision(2);

    for (int i = 0; i < count; i++) { //for each item in the list
        cout << list[i].desc << " (" << list[i].part
             << ") $" << list[i].price << endl;
    }
}