#include <iostream>
#include <cassert>
#include <string>
#include <sstream>
#include "node.h"
#include "polylist.h"
#include "polyman.h"

using namespace std;

int main() {
//node::node(const int exponent, const int coefficient, const char variable, node* next) :
    node n(0,0,'x',NULL);
    node n1(0,1,'x',NULL);
    node n2(1,0,'x',NULL);
    node n3(1,1,'x',NULL);
    node n4(1,'x',NULL);
    node n5(0,'x',NULL);
    node n6(1,'x',NULL);

    stringstream s;

    s << n;
    assert(s.str() == "");
    s.str("");

    s << n1;
    assert(s.str() == "1");
    s.str("");

    s << n2;
    assert(s.str() == "");
    s.str("");

    s << n3;
    assert(s.str() == "x");
    s.str("");

    string a1 = "1 x ^ 1";
    vector<string> v = parse_expression(a1);
    assert(v[0] == "1");
    assert(v[1] == "x");
    assert(v[3] == "1");
    assert(is_valid(v) == true);
    
    string a2 = "123 g ^ 152";
    v = parse_expression(a2);
    assert(is_valid(v) == true);

    string a3 = "a b c";
    v = parse_expression(a3);
    assert(is_valid(v) == false);

    string a4 = "";
    v = parse_expression(a4);
    assert(is_valid(v) == false);
    
    string a5 = "1 x";
    v = parse_expression(a5);
    assert(is_valid(v) == true);

    string a6 = "x";
    v = parse_expression(a6);
    assert(is_valid(v) == true);

    string a7 = "morethanonecharacter";
    v = parse_expression(a7);
    assert(is_valid(v) == false);
    
    string a8 = "$";
    v = parse_expression(a8);
    assert(is_valid(v) == false);

    string a9 = "1 & ^ x";
    v = parse_expression(a9);
    assert(is_valid(v) == false);

    string b1 = "123 g ^ %";
    v = parse_expression(b1);
    assert(is_valid(v) == false);

    string b2 = "1r32 g ^ 152";
    v = parse_expression(b2);
    assert(is_valid(v) == false);
    
    string b3 = "123 ^ 152";
    v = parse_expression(b3);
    assert(is_valid(v) == false);

    string b4 = "123 g ^";
    v = parse_expression(b4);
    assert(is_valid(v) == false);

    string b5 = "5 x ^ -2";
    v = parse_expression(b5);
    assert(is_valid(v) == false);
    
    polylist p;
    stringstream sr;

    p.insert("x");
    sr << p.printList();
    assert(sr.str() == "1");

    p.insert("2 x");
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "3");

    p.insert("-5 x");
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "-2");

    assert(p.size() == 1);

    p.insert("x ^ 1");
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "x + -2");

    assert(p.size() == 2);

    p.insert("x ^ 4");
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "x ^ 4 + x + -2");


    assert(p.size() == 3);

    p.insert("x ^ 5");
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "x ^ 5 + x ^ 4 + x + -2");

    p.insert("x ^ -1");
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "x ^ 5 + x ^ 4 + x + -2");

    p.insert("x ^ 4");
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "x ^ 5 + 2 x ^ 4 + x + -2");

    p.insert("x ^ 4");
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "x ^ 5 + 3 x ^ 4 + x + -2");

    p.insert("x ^ 4");
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "x ^ 5 + 4 x ^ 4 + x + -2");

    p.insert("x ^ 5");
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "2 x ^ 5 + 4 x ^ 4 + x + -2");


    assert(p.size() == 4);

    p.insert("x ^ 1");
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "2 x ^ 5 + 4 x ^ 4 + 2 x + -2");

    p.insert("x");
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "2 x ^ 5 + 4 x ^ 4 + 2 x + -1");

    p.insert("x ^ 7");
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "x ^ 7 + 2 x ^ 5 + 4 x ^ 4 + 2 x + -1");

    p.insert("x ^ -7");
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "x ^ 7 + 2 x ^ 5 + 4 x ^ 4 + 2 x + -1");

    p.insert("x ^ 7");
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "2 x ^ 7 + 2 x ^ 5 + 4 x ^ 4 + 2 x + -1");

    assert(p.size() == 5);

    p.insert("2 x ^ 3");
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "2 x ^ 7 + 2 x ^ 5 + 4 x ^ 4 + 2 x ^ 3 + 2 x + -1");


    p.insert("2 x ^ 3");
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "2 x ^ 7 + 2 x ^ 5 + 4 x ^ 4 + 4 x ^ 3 + 2 x + -1");


    p.insert("2 x ^ 2");
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "2 x ^ 7 + 2 x ^ 5 + 4 x ^ 4 + 4 x ^ 3 + 2 x ^ 2 + 2 x + -1");

    p.insert("2 x ^ 7");
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "4 x ^ 7 + 2 x ^ 5 + 4 x ^ 4 + 4 x ^ 3 + 2 x ^ 2 + 2 x + -1");

    p.insert("2 x ^ 0");
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "4 x ^ 7 + 2 x ^ 5 + 4 x ^ 4 + 4 x ^ 3 + 2 x ^ 2 + 2 x + 1");

    p.insert("-4 x ^ 4");
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "4 x ^ 7 + 2 x ^ 5 + 4 x ^ 3 + 2 x ^ 2 + 2 x + 1");

    p.insert("2 x ^ 3");
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "4 x ^ 7 + 2 x ^ 5 + 6 x ^ 3 + 2 x ^ 2 + 2 x + 1");

    p.insert("8 x ^ 4");
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "4 x ^ 7 + 2 x ^ 5 + 8 x ^ 4 + 6 x ^ 3 + 2 x ^ 2 + 2 x + 1");

    p.insert("2 x ^ -3");
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "4 x ^ 7 + 2 x ^ 5 + 8 x ^ 4 + 6 x ^ 3 + 2 x ^ 2 + 2 x + 1");

    p.insert("-1 x ^ 3");
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "4 x ^ 7 + 2 x ^ 5 + 8 x ^ 4 + 5 x ^ 3 + 2 x ^ 2 + 2 x + 1");

    p.insert("-2 x ^ 7");
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "2 x ^ 7 + 2 x ^ 5 + 8 x ^ 4 + 5 x ^ 3 + 2 x ^ 2 + 2 x + 1");

    p.insert("2 x ^ 9");
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "2 x ^ 9 + 2 x ^ 7 + 2 x ^ 5 + 8 x ^ 4 + 5 x ^ 3 + 2 x ^ 2 + 2 x + 1");

    p.insert("-2 x ^ 9");
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "2 x ^ 7 + 2 x ^ 5 + 8 x ^ 4 + 5 x ^ 3 + 2 x ^ 2 + 2 x + 1");

    p.insert("10 x ^ 7");
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "12 x ^ 7 + 2 x ^ 5 + 8 x ^ 4 + 5 x ^ 3 + 2 x ^ 2 + 2 x + 1");

    p.insert("x");
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "12 x ^ 7 + 2 x ^ 5 + 8 x ^ 4 + 5 x ^ 3 + 2 x ^ 2 + 2 x + 2");

    p.insert("x ^ 7");
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "13 x ^ 7 + 2 x ^ 5 + 8 x ^ 4 + 5 x ^ 3 + 2 x ^ 2 + 2 x + 2");

    p.insert("-10 x ^ 7");
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "3 x ^ 7 + 2 x ^ 5 + 8 x ^ 4 + 5 x ^ 3 + 2 x ^ 2 + 2 x + 2");

    p.insert("10 x");
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "3 x ^ 7 + 2 x ^ 5 + 8 x ^ 4 + 5 x ^ 3 + 2 x ^ 2 + 2 x + 12");

    p.insert("-10 x");
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "3 x ^ 7 + 2 x ^ 5 + 8 x ^ 4 + 5 x ^ 3 + 2 x ^ 2 + 2 x + 2");

    p.insert("-2 x");
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "3 x ^ 7 + 2 x ^ 5 + 8 x ^ 4 + 5 x ^ 3 + 2 x ^ 2 + 2 x");

    p.insert("2 x ^ 0");
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "3 x ^ 7 + 2 x ^ 5 + 8 x ^ 4 + 5 x ^ 3 + 2 x ^ 2 + 2 x + 2");

    p.insert("x ^ 3");
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "3 x ^ 7 + 2 x ^ 5 + 8 x ^ 4 + 6 x ^ 3 + 2 x ^ 2 + 2 x + 2");

    p.insert("");
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "3 x ^ 7 + 2 x ^ 5 + 8 x ^ 4 + 6 x ^ 3 + 2 x ^ 2 + 2 x + 2");

    p.insert("-3 x ^ 7");
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "2 x ^ 5 + 8 x ^ 4 + 6 x ^ 3 + 2 x ^ 2 + 2 x + 2");
    
    p.insert("-2 x ^ 5");
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "8 x ^ 4 + 6 x ^ 3 + 2 x ^ 2 + 2 x + 2");

    p.insert("-2 x ^ 2");
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "8 x ^ 4 + 6 x ^ 3 + 2 x + 2");

    p.insert("-3 x ^ 7");
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "-3 x ^ 7 + 8 x ^ 4 + 6 x ^ 3 + 2 x + 2");

    p.insert("-3 x ^ 7");
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "-6 x ^ 7 + 8 x ^ 4 + 6 x ^ 3 + 2 x + 2");

    p.insert("9 x ^ 7");
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "3 x ^ 7 + 8 x ^ 4 + 6 x ^ 3 + 2 x + 2");

    p.clear();
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "");

    assert(p.size() == 0);

    p.insert("9 x ^ 7");
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "9 x ^ 7");

    assert(p.size() == 1); 

    p.clear();
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "");

    assert(p.size() == 0);

    p.insert("x ^ 7");
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "x ^ 7");

    p.insert("-x ^ 7");
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "");

    p.clear();
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "");

    assert(p.size() == 0);

    p.insert("2 x");
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "2");

    p.clear();
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "");

    assert(p.size() == 0);

    p.insert("x");
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "1");

    p.remove(0);
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "");

    p.insert("-x");
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "-1");

    p.insert("2 x");
    sr.str("");
    sr << p.printList();
    assert(sr.str() == "1");

    node n7(3, -1, 'x',NULL);

    polyman m;
    m.addLists();
    m.subtractLists();
    m.fillListOne("x");
    m.fillListOne("2 x");
    m.fillListOne("3 x ^ 3");
    m.fillListOne("4aqkjx");
    m.fillListOne("-4 x ^ 323");
    m.fillListOne("-2 x ^ 400");
    m.fillListOne("x");
    m.fillListOne("x");
    m.fillListOne("x");
    m.fillListOne("x");
    m.fillListTwo("-6 x");
    m.fillListTwo("-4 x ^ 323");
    m.fillListTwo("-x ^ 3");
    m.fillListTwo("7 x ^ 8");
    m.fillListTwo("4 x ^ 3");
    m.fillListTwo("-x");
    m.fillListTwo("14 x");
    m.addLists();
    m.subtractLists();
}
