#include <assert.h>
#include <iostream>
#include "SinglyLinkedList.h"

void test_constructor() {
    std::cout << "TEST CONSTRUCTOR" << std::endl;
    SinglyLinkedList<int> lst1 = {};
    std::cout << "Expected: 0" << std::endl;
    std::cout << "Actual  : " <<  lst1.size() << std::endl;

    SinglyLinkedList<int> lst2 = {100, 200, 300, 400, 500};
    std::cout << "Expected: 100   200   300   400   500   5" << std::endl;
    std::cout << "Actual  : ";
    for (int i = 0; i < 5; i++) {
        std::cout << *lst2.at(i) << "   ";
    }
    std::cout << lst2.size() << std::endl;
}

void test_remove() {
    std::cout << "TEST REMOVE" << std::endl;
    SinglyLinkedList<int> lst1 = {100, 200, 300, 400, 500};
    std::cout << "Expected: 200   300   400   500   4" << std::endl;
    lst1.remove(0);
    std::cout << "Actual  : ";
    for (int i = 0; i < 4; i++) {
        std::cout << *lst1.at(i) << "   ";
    }
    std::cout << lst1.size() << std::endl;
    lst1.remove(3);
    std::cout << "Expected: 200   300   400   3" << std::endl;
    std::cout << "Actual  : ";
    for (int i = 0; i < 3; i++) {
        std::cout << *lst1.at(i) << "   ";
    }
    std::cout << lst1.size() << std::endl;
}

void test_insert() {
    std::cout << "TEST INSERT" << std::endl;
    SinglyLinkedList<int> lst1 = {100, 200, 300, 400};
    lst1.insert(3, 350);
    std::cout << "Expected: 100   200   300   350   400   5" << std::endl;
    std::cout << "Actual  : ";
    for (int i = 0; i < 5; i++) {
        std::cout << *lst1.at(i) << "   ";
    }
    std::cout << lst1.size() << std::endl;

    lst1.insert(0, 50);
    std::cout << "Expected: 50   100   200   300   350   400   6" << std::endl;
    std::cout << "Actual  : ";
    for (int i = 0; i < 6; i++) {
        std::cout << *lst1.at(i) << "   ";
    }
    std::cout << lst1.size() << std::endl;
}

void test_push_back() {
    std::cout << "TEST PUSH_BACK" << std::endl;
    SinglyLinkedList<int> lst = {100, 200, 300, 400, 500};
    lst.push_back(600);
    std::cout << "Expected: 100   200   300   400   500   600   6" << std::endl;
    std::cout << "Actual  : ";
    for (int i = 0; i < 6; i++) {
        std::cout << *lst.at(i) << "   ";
    }
    std::cout << lst.size() << std::endl;
}

void test_push_front() {
    std::cout << "TEST PUSH_FRONT" << std::endl;
    SinglyLinkedList<int> lst = {100, 200, 300, 400, 500};
    lst.push_front(50);
    std::cout << "Expected: 50   100   200   300   400   500   6" << std::endl;
    std::cout << "Actual  : ";
    for (int i = 0; i < 6; i++) {
        std::cout << *lst.at(i) << "   ";
    }
    std::cout << lst.size() << std::endl;
}

void test_append() {
    std::cout << "TEST APPEND" << std::endl;
    SinglyLinkedList<int> lst1 = {100, 200, 300, 400, 500};
    SinglyLinkedList<int> lst2 = {600, 700, 800, 900};
    SinglyLinkedList<int> lst3 = {};
    lst1.append(lst2);

    std::cout << "Expected: 100   200   300   400   500   600   700   800   900   9" << std::endl;
    std::cout << "Actual  : ";
    for (int i = 0; i < 9; i++) {
        std::cout << *lst1.at(i) << "   ";
    }
    std::cout << lst1.size() << std::endl;
    lst1.append(lst3);
    std::cout << "Expected: 100   200   300   400   500   600   700   800   900   9" << std::endl;
    std::cout << "Actual  : ";
    for (int i = 0; i < 9; i++) {
        std::cout << *lst1.at(i) << "   ";
    }
    std::cout << lst1.size() << std::endl;
}

void test_sum() {
    std::cout << "TEST SUM" << std::endl;
    SinglyLinkedList<int> lst1 = {100, 200, 300, 400, 500};
    std::cout << "Expected: 1500" << std::endl;
    std::cout << "Actual  : " << sum(lst1) << std::endl;
    std::cout << "Expected: 0" << std::endl;
    SinglyLinkedList<int> lst2 = {};
    std::cout << "Actual  : " << sum(lst2) << std::endl;
}

int main() {
    test_constructor();
    test_remove();
    test_insert();
    test_push_back();
    test_push_front();
    test_append();
    test_sum();
}

