#include "mqueue.h"
#include <sstream>
#include <random>

class Tester
{
private:
static int getImportance(const Order& order) {
    return order.getImportance();
}
Order genRandomOrder();

public:
bool testConstructor();
bool testCopyConstructor();
bool testCopyConstructorEmpty();
bool testCopyConstructorNotEmpty();
bool testDestructor();

};

//Main function to run tests in
int main() {
    Tester tester;
    bool constructorResult = tester.testConstructor();
    cout << (constructorResult ? "Constructor test passed\n" : "Constructor test failed\n") << endl;
    bool copyConstructorResult = tester.testCopyConstructor();
    cout << (copyConstructorResult ? "Copy constructor test passed\n" : "Copy constructor test failed\n") << endl;
    bool copyConstructorEmptyResult = tester.testCopyConstructorEmpty();
    cout << (copyConstructorEmptyResult ? "Copy constructor empty test passed\n" : "Copy constructor empty test failed\n") << endl;
    bool copyConstructorNotEmptyResult = tester.testCopyConstructorNotEmpty();
    cout << (copyConstructorNotEmptyResult ? "Copy constructor not empty test passed\n" : "Copy constructor not empty test failed\n") << endl;
    bool destructorResult = tester.testDestructor();
    cout << (destructorResult ? "Destructor test passed\n" : "Destructor test failed\n") << endl;
}

bool Tester::testConstructor()
{
    // Create an MQueue instance with specific heap type and structure
    MQueue testQueue(getImportance, MINHEAP, LEFTIST);

    // Check initial conditions for MQueue
    bool CorrectPrioFn = (testQueue.getPriorityFn() == getImportance);
    bool CorrectHeapType = (testQueue.getHeapType() == MINHEAP);
    bool CorrectStructure = (testQueue.getStructure() == LEFTIST);
    bool isEmpty = (testQueue.numOrders() == 0);

    // Return true if all conditions pass false otherwise
    return CorrectPrioFn && CorrectHeapType && CorrectStructure && isEmpty;
}

bool Tester::testCopyConstructor()
{
    // Create an MQueue instance with specific heap type and structure
    MQueue testQueue(getImportance, MINHEAP, LEFTIST);

    // Insert some orders into the original queue
    for (int i = 0; i < 50; i++) {
        Order randomOrder = genRandomOrder();
        testQueue.insertOrder(randomOrder);
        cout << "Order inserted: " << randomOrder << endl;
    }

    // Create a copy of the original queue using the copy constructor
    MQueue copiedQueue(testQueue);

    // Verify that the copied queue has the same state as the original queue
    bool SamePrioFn = (copiedQueue.getPriorityFn() == testQueue.getPriorityFn());
    bool SameHeapType = (copiedQueue.getHeapType() == testQueue.getHeapType());
    bool SameStructure = (copiedQueue.getStructure() == testQueue.getStructure());
    bool SameNumOrders = (copiedQueue.numOrders() == testQueue.numOrders());

    //testQueue.dump();

    // Return true if all conditions pass false otherwise
    return SamePrioFn && SameHeapType && SameStructure && SameNumOrders;
}

bool Tester::testCopyConstructorEmpty()
{
    //Create an Mqueue instance with specific heap type and structure
    MQueue testQueue(getImportance, MINHEAP, SKEW);

    //Create a copy of the original queue using the copy constructor
    MQueue copiedQueue(testQueue);

    //Verify that the copied queue is empty
    bool SameHeapType = (copiedQueue.getHeapType() == testQueue.getHeapType());
    bool SameStructure = (copiedQueue.getStructure() == testQueue.getStructure());
    bool isEmpty = (copiedQueue.numOrders() == 0);

    //Return true if the copied queue is empty false otherwise
    return isEmpty && SameStructure && SameHeapType;
}

bool Tester::testCopyConstructorNotEmpty()
{
    //Create an Mqueue instance with specific heap type and structure
    MQueue testQueue(getImportance, MINHEAP, LEFTIST);

    //Insert some orders into the original queue
    for(int i = 0; i < 50; i++) {
        Order randomOrder = genRandomOrder();
        testQueue.insertOrder(randomOrder);
    }

    //Create a copy of the original queue using the copy constructor
    MQueue copiedQueue(testQueue);

    //Verify that the copied queue has the same state as the original queue
    bool SamePrioFn = (copiedQueue.getPriorityFn() == testQueue.getPriorityFn());
    bool SameHeapType = (copiedQueue.getHeapType() == testQueue.getHeapType());
    bool SameStructure = (copiedQueue.getStructure() == testQueue.getStructure());
    bool SameNumOrders = (copiedQueue.numOrders() == testQueue.numOrders());

    //Return true if all conditions pass false otherwise
    return SamePrioFn && SameHeapType && SameStructure && SameNumOrders;
  
}

bool Tester::testDestructor()
{
    // Create an MQueue instance with specific heap type and structure 
    MQueue* testQueue = new MQueue(getImportance, MAXHEAP, LEFTIST);

    //Insert orders into the queue
    testQueue->insertOrder(Order("Customer, 1", 1, 1, 1, 1, 1, 1, 1, 1));
    testQueue->insertOrder(Order("Customer, 2", 2, 2, 2, 2, 2, 2, 2, 2));
    testQueue->insertOrder(Order("Customer, 3", 3, 3, 3, 3, 3, 3, 3, 3));
    testQueue->insertOrder(Order("Customer, 4", 4, 4, 4, 4, 4, 4, 4, 4));
    testQueue->insertOrder(Order("Customer, 5", 5, 5, 5, 5, 5, 5, 5, 5));
    
    //Store the number of orders in the queue
    int numOrders = testQueue->numOrders();
    //Then we delete the queue to call the destructor
    delete testQueue;

    //We expect 5 orders to have been added to the queue
    //Can't really check i guess without valgrind for now.
    return (numOrders > 0);
}


Order Tester::genRandomOrder()
{
        // Initialize random number generator
        random_device rd; 
        mt19937 gen(rd()); // Seed the generator with the random number

        //97 - 122 is the ascii value for 'a' - 'z'
        uniform_int_distribution<> charGen(97, 122); 
        uniform_int_distribution<> fifoGen(MINONE, MAX50);
        uniform_int_distribution<> processTimeGen(MINONE, MAX12);
        uniform_int_distribution<> dueTimeGen(MINONE, MAX12);
        uniform_int_distribution<> slackTimeGen(MINONE, MAX12);
        uniform_int_distribution<> materialGen(MINZERO, MAX100);
        uniform_int_distribution<> importanceGen(MINONE, MAX100);
        uniform_int_distribution<> workersGen(MINONE, MAX12);
        uniform_int_distribution<> quantityGen(MIN1000, MAX10000);

        // Generate a random customer name of length 5
        string customer;
        for (int i = 0; i < 5; ++i) {
            customer += static_cast<char>(charGen(gen));
        }

        // Generate random values for rest of the order
        int fifo = fifoGen(gen);
        int process = processTimeGen(gen);
        int due = dueTimeGen(gen);
        int slack = slackTimeGen(gen);
        int material = materialGen(gen);
        int importance = importanceGen(gen);
        int workers = workersGen(gen);
        int quantity = quantityGen(gen);

        // Return the created Order
        return Order(customer, fifo, process, due, slack, material, importance, workers, quantity);
} 

i can't figure out why my randomorder function wont generate random numbers/characters

Order inserted: Customer: osjxa, importance: 17, quantity: 3852, order placement time: 30
Order inserted: Customer: osjxa, importance: 17, quantity: 3852, order placement time: 30
Order inserted: Customer: osjxa, importance: 17, quantity: 3852, order placement time: 30
Order inserted: Customer: osjxa, importance: 17, quantity: 3852, order placement time: 30
Order inserted: Customer: osjxa, importance: 17, quantity: 3852, order placement time: 30
Order inserted: Customer: osjxa, importance: 17, quantity: 3852, order placement time: 30
Order inserted: Customer: osjxa, importance: 17, quantity: 3852, order placement time: 30
Order inserted: Customer: osjxa, importance: 17, quantity: 3852, order placement time: 30
Order inserted: Customer: osjxa, importance: 17, quantity: 3852, order placement time: 30
Order inserted: Customer: osjxa, importance: 17, quantity: 3852, order placement time: 30
Order inserted: Customer: osjxa, importance: 17, quantity: 3852, order placement time: 30
Order inserted: Customer: osjxa, importance: 17, quantity: 3852, order placement time: 30
Order inserted: Customer: osjxa, importance: 17, quantity: 3852, order placement time: 30
Order inserted: Customer: osjxa, importance: 17, quantity: 3852, order placement time: 30
Order inserted: Customer: osjxa, importance: 17, quantity: 3852, order placement time: 30
Order inserted: Customer: osjxa, importance: 17, quantity: 3852, order placement time: 30
Order inserted: Customer: osjxa, importance: 17, quantity: 3852, order placement time: 30
Order inserted: Customer: osjxa, importance: 17, quantity: 3852, order placement time: 30
Order inserted: Customer: osjxa, importance: 17, quantity: 3852, order placement time: 30
Order inserted: Customer: osjxa, importance: 17, quantity: 3852, order placement time: 30
Order inserted: Customer: osjxa, importance: 17, quantity: 3852, order placement time: 30
Order inserted: Customer: osjxa, importance: 17, quantity: 3852, order placement time: 30
Order inserted: Customer: osjxa, importance: 17, quantity: 3852, order placement time: 30
Order inserted: Customer: osjxa, importance: 17, quantity: 3852, order placement time: 30
Order inserted: Customer: osjxa, importance: 17, quantity: 3852, order placement time: 30
Order inserted: Customer: osjxa, importance: 17, quantity: 3852, order placement time: 30
Order inserted: Customer: osjxa, importance: 17, quantity: 3852, order placement time: 30
Order inserted: Customer: osjxa, importance: 17, quantity: 3852, order placement time: 30
Order inserted: Customer: osjxa, importance: 17, quantity: 3852, order placement time: 30
Order inserted: Customer: osjxa, importance: 17, quantity: 3852, order placement time: 30
Order inserted: Customer: osjxa, importance: 17, quantity: 3852, order placement time: 30
Order inserted: Customer: osjxa, importance: 17, quantity: 3852, order placement time: 30
Order inserted: Customer: osjxa, importance: 17, quantity: 3852, order placement time: 30
Order inserted: Customer: osjxa, importance: 17, quantity: 3852, order placement time: 30
Order inserted: Customer: osjxa, importance: 17, quantity: 3852, order placement time: 30
Order inserted: Customer: osjxa, importance: 17, quantity: 3852, order placement time: 30
Order inserted: Customer: osjxa, importance: 17, quantity: 3852, order placement time: 30
Order inserted: Customer: osjxa, importance: 17, quantity: 3852, order placement time: 30
Order inserted: Customer: osjxa, importance: 17, quantity: 3852, order placement time: 30
Order inserted: Customer: osjxa, importance: 17, quantity: 3852, order placement time: 30
Order inserted: Customer: osjxa, importance: 17, quantity: 3852, order placement time: 30
Order inserted: Customer: osjxa, importance: 17, quantity: 3852, order placement time: 30
Order inserted: Customer: osjxa, importance: 17, quantity: 3852, order placement time: 30
Order inserted: Customer: osjxa, importance: 17, quantity: 3852, order placement time: 30
Order inserted: Customer: osjxa, importance: 17, quantity: 3852, order placement time: 30
Order inserted: Customer: osjxa, importance: 17, quantity: 3852, order placement time: 30
Order inserted: Customer: osjxa, importance: 17, quantity: 3852, order placement time: 30
Order inserted: Customer: osjxa, importance: 17, quantity: 3852, order placement time: 30
Order inserted: Customer: osjxa, importance: 17, quantity: 3852, order placement time: 30
Order inserted: Customer: osjxa, importance: 17, quantity: 3852, order placement time: 30 

is the output when called