#include <iostream>
using namespace std;

#include "fstring.hpp"
#include "fstack.hpp"
#include "fvector.hpp"
#include "ftree.hpp"

const char * hello = "Hello";
const char * world = "World";

void print(baseFstr * Fstr)
{
    cout << Fstr->size() << endl;
    for (int i=0;i<Fstr->size();i++)
        cout << Fstr->at(i);
    cout << endl;
}

int main()
{

    //test fstring
    fstring::base * Fstr,
             *Fsub;
    
    Fstr = new fstring::ref(hello);
    print(Fstr);
    Fstr = new fstring::insertRef(Fstr,world,5);
    print(Fstr);
    Fstr = new fstring::insertNu(Fstr," ", 5);
    print(Fstr);
    Fstr = new fstring::insertNu(Fstr," all the ",5,6);
    print(Fstr);
    Fsub = new fstring::nu("!!!");
    Fstr = new fstring::insertRef(Fstr," human of this ", 13,14);
    print(Fstr);
    Fstr = new fstring::insertSub(Fstr,Fsub,33);
    print(Fstr);
    Fstr = new fstring::trim(Fstr,5,13);
    print(Fstr);
    Fstr = new fstring::sub(Fstr,15,25);
    print(Fstr);
    Fstr = new fstring::toUpper(Fstr);
    print(Fstr);
    
    cout << "\nnow let undo all this modif\n\n";
    
    do{
        print(Fstr);
        Fstr = Fstr->undo();
    }while(Fstr);
    
    //test fstack
    cout << endl << "now the stack\n";
    typedef fstack<int> s;
    s::base * stk = new s::push(0);

    
    stk = new s::push(5);
    stk = new s::push(8);
    stk = new s::push(1);
    stk = stk->pop();
    stk = new s::push(2);
    stk = new s::push(8);

    for (int i=0;i<stk->size();i++)
        cout << stk->peek(i) << " ";

    cout << endl;
    
    //test the fvector
    cout << "test the f*#%ing vector\n";
    int arr [16] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
    typedef fvector<int> v;
    v::base * fv,
            * fv2;
    fv = new v::nu(10,15);
    
    fv2 = new v::ref(arr,16);
    for (int i=0;i<fv2->size();i++)
        cout << fv2->at(i) << " ";
    cout << endl;
    fv2 = new v::resize(fv2,18,-1);
    for (int i=0;i<fv2->size();i++)
        cout << fv2->at(i) << " ";
    cout << endl;
    fv2 = new v::insert(fv2,arr,16,17,17);
    for (int i=0;i<fv2->size();i++)
        cout << fv2->at(i) << " ";
    cout << endl;
    fv2 = new v::trim(fv2,5,6);
    for (int i=0;i<fv2->size();i++)
        cout << fv2->at(i) << " ";
    cout << endl;
    fv2 = new v::sub(fv2,2,10);
    for (int i=0;i<fv2->size();i++)
        cout << fv2->at(i) << " ";
    cout << endl;
    
    //test ftree
    int test[9] = {5,9,1,3,8,2,7,6,4};
    cout << "test de l'arbre qui à l'air trop simple pour etre fonctionnel\n";
    baseFtree<int,int> * t = 0;
    const baseFtree<int,int> * tmp = t;

    for (int i=0;i<9;i++)
    {
        t = new baseFtree<int,int>(t,96+test[i],test[i]);
        cout << "insert " << (char)(test[i]+96) << ":" << test[i] << endl;
    }
    
    for (int i=0;i<10;i++)
    {
        cout << "key : " << (char)(96+i) << " => found : " << t->at(96+i) << endl;
    }
    
    cout << t->size() << " big\n";

    while (tmp)
    {
        cout << "ok\n";
        tmp = tmp->undo();
    }
    cout << ".";

    return 0;
}
