#include "pla.h"

// -----------------------------------------------------------------------
Pla::Pla(const char *f, int pocet_iter)
{
    file.open(f);
    if (!file.is_open())
        throw std::runtime_error("cannot open input file");
    pocet_iteraci = pocet_iter;
}

// -----------------------------------------------------------------------
Pla::Pla(const char *f)
{
    file.open(f);
    if (!file.is_open())
        throw std::runtime_error("cannot open input file");
    pocet_iteraci = 1;
}

// -----------------------------------------------------------------------
void Pla::read_header()
{
    file >> noskipws;

    while(true){
        file >> token;
//         cout << token;

        if (token == '.'){
            file >> token;
            //vstupy
            if (token == 'i'){
                file >> token;
                
                if (token == 'l'){
                    while(token != '\n')
                        file >> token;
                    continue;
                }
                file >> token;
                if (isdigit(token)){
                    inputs = token - '0';
    
                    while(isdigit(token)){
                        file >> token;
                        if (isdigit(token)) {
                            inputs *= 10;
                            inputs += (token - '0');
                        }
                    }
                }
                if (token != '\n')
                    file >> token;
                continue;
            }
            
            //vystupy
            if (token == 'o'){
                file >> token;
                if (token == 'l'){
                    while(token != '\n')
                        file >> token;
                    continue;
                }
                file >> token;
                if (isdigit(token)){
                    outputs = token - '0';
    
                    while(isdigit(token)){
                        file >> token;
                        if (isdigit(token)) {
                            outputs *= 10;
                            outputs += (token - '0');
                        }
                    }
                }
                if (token != '\n')
                    file >> token;
                continue;
            }
            
            while(token != '\n')
                file >> token;
        }
        else
            break;
    }
}

// -----------------------------------------------------------------------
bool Pla::get_term(char *term)
{
//     char token;
    int i = 0;

    for(i = 0;i < inputs;i++){
        if (isdigit(token) || token == '-'){
            if (isdigit(token))
                term[i] = token;
            else
                if (token == '-')
                    term[i] = '2';
        }
        else
            return false;
        
        file >> token;
    }
    
    while(token != '\n')
        file >> token;
    
    file >> token;

//     pupik->print_array(term, inputs);
//     cout << endl;

    return true;
}

// -----------------------------------------------------------------------
bool Pla::run()
{
    char *term;
//     int dc_count;
    long pocet_top_termu = 0;
    
    read_header();

    term = new char[inputs];

//     cout << inputs << ", " << outputs << endl;
//     cout << "pocet iteraci: " << pocet_iteraci << endl;
    pupik = new Pupik(inputs, outputs);

    while(get_term(term)){
//         pupik->print_array(term, inputs);
//         cout << " 1" << endl;
        pupik->mt_insert(term);
    }

//     cout << "vlozeno" << endl;
//     for(unsigned int i = 0;i < pupik->top_terms.size();i++)
//         cout << pupik->top_terms[i].dc_count << " ";
//     cout << endl;

    pupik->mt_divide_and_merge();
//     cout << "test" << endl;
    
    for(int i = 1;i < pocet_iteraci*inputs;i++){
        pupik->mt_merge_leaves();
//         cout << "listy slouceny" << endl;
        pupik->mt_divide_and_merge();
//         cout << "stromy rozdeleny" << endl;
    }

    for(int i = 0;i < inputs;i++)
        term[i] = '2';

    pupik->pocet_termu = 0;
    pupik->mt_print(NULL);
//     cout << pupik->pocet_termu << endl;
    pocet_top_termu = (pupik->pocet_termu > 100) ? pupik->pocet_termu / 100 : 10;
//     cout << pocet_top_termu;
    pupik->mt_minimize_subset(pocet_top_termu);
    
    cout << ".i " << inputs << endl;
    cout << ".o " << outputs << endl;
    cout << ".p " << pupik->pocet_termu << endl;
    cout << ".type fd" << endl;
    pupik->mt_export(pupik->get_tree(), term, "1", 0);
    cout << ".e" << endl;

    delete[] term;
    delete pupik;
    return true;
}


