#ifndef pupikH
#define pupikH

#include <stdio.h>
#include <iostream>
#include <stdexcept>
#include <vector>
#include <algorithm>

using namespace std;

// trida popisujici jeden uzel minimalizacniho ternarniho stromu
// -----------------------------------------------------------------
class I_buffer {
    public:
        I_buffer *one;
        I_buffer *zero;
        I_buffer *dc;

        I_buffer(){ one = zero = dc = NULL; /*cout << "construct" << endl;*/ };
        ~I_buffer(){ if (one) delete one; if (zero) delete zero; if (dc) delete dc; /*cout << "destruct" << endl; */};
        bool is_leaf(void) { if (one == NULL && zero == NULL && dc == NULL) return true; return false;}
};


// trida popisujici prvek ze seznamu termu z nejvetsim pocetm don't-care (kvuli podmnozinam)
// -----------------------------------------------------------------------------------------
class Top_term {
    public:
        char *term;
        int dc_count;
        
        Top_term(int size){ /*cout << "konstrukt" << endl; */term = new char[size]; dc_count = 0; };
        ~Top_term(){ /*cout << "destruct: " << dc_count << endl; delete[] term;*/ };
        int operator<(const Top_term&) const;
};

// trida realizujici minimalizaci vystupni logicke funkce 
// ------------------------------------------------------
class Pupik {
    // privatni data
    I_buffer *min_tree;
    long count;
    int inputs_num;
    int outputs_num;
    int same_term;

public:
    vector<Top_term> top_terms;
    long pocet_termu;
    
    Pupik(int, int);
    ~Pupik(){ delete min_tree; };
    
    I_buffer *get_tree(){ return min_tree; };
    void mt_insert(char *);
    void mt_top_term(char *, int, long);
    void mt_generate_top_terms(I_buffer *, char *, int, long);
    void mt_minimize_subset(long);
    bool mt_minimize_subset_recursive(I_buffer *, char *, char *, int);
    void mt_merge_leaves(void);
    void mt_merge_leaves_recursive(I_buffer *, I_buffer *);
    void mt_print_recursive(I_buffer *, char *, int, char *);
    void mt_print(char *);
    int mt_count(I_buffer *);
    void mt_divide_tree(void);
    void mt_divide_and_merge(void);
    void mt_insert_leaf_recursive(I_buffer *, int);
    void mt_merge_trees(I_buffer *, I_buffer *);
    void mt_merge_trees(I_buffer *, I_buffer *, I_buffer *);
    void mt_export(I_buffer *, char *, char *, int);
    void print_array(char *, int);
};

#endif
