//  global_objects.h
//  
//  Created by Mikhail Auguston on 2/8/19.
//
//***** VIEW object infrastructure for trace list ******
using namespace std;

//-------------------------------------------------
class report_object{
public:
    string title;
    vector<string> report_contents;
    // constructor
    report_object(){ title = " "; }
    
    void clean(){
        report_contents.clear();
    }
    //--- print json for Report objects
    void print_report_json(){
        JSON<< endl<< "{\"REPORT\":["<< "\""<< title<< "\"";
        vector<string>::iterator p;
        for(p = report_contents.begin(); p != report_contents.end(); p++){
            JSON<<",\"" <<  *p<< "\"";
        }
        JSON<<"]}"<< endl;
    }
};

//--------------------------------------------------
class graph_object{
public:
    string title;

    // unique_node_id -> node_label
    vector<string> nodes;
    
    // from_node_id -> <to_node_id, arrow_label>
    // no repetitions of <to_node_id, arrow_label> for same from_node_id
    multimap<int, pair<int, string> > arrows; // edges with arrowheads
    multimap<int, pair<int, string> > lines; // edges without arrowheads
 //=============================================
    
    // constructor
    graph_object(){ title = " "; }
    
    void clean(){
        nodes.clear();
        arrows.clear();
        lines.clear();
    }
    
    // NEW NODE()
    int create_new_node(string label){
        nodes.push_back(label);
        return nodes.size() - 1;
    }
    
    // find the last appearance of a node with a given label
    int find_node(string label){
        int result = -1;
        for(int i = 0; i < nodes.size(); i++){
            if(nodes[i] == label) result = i;
        }
        return result;
    }
    
    // LAST NODE()
    int find_or_create_new_node(string label){
        int x = find_node(label);
        if(x >= 0) return x;
        else return create_new_node(label);
    }
    
    void add_arrow(int n1, int n2, string arrow_label){
        // if n1 or n2 does not exist - do nothing
        if(n1 < 0 || n2 < 0 || n1 >= nodes.size() || n2 >= nodes.size()) return;
        multimap<int, pair<int, string> >:: iterator p;
        pair<int, string> p3;
        for(p = arrows.begin(); p != arrows.end(); p++){
            p3 = p->second;
            // if arrow with that label already exists - do nothing
            if(p->first == n1 && p3.first == n2 && p3.second == arrow_label) return;
        }
        // arrow n1 -> n2, arrow_label has not been found
        arrows.insert(pair<int, pair<int, string> >(n1, pair<int, string>(n2, arrow_label)));
    }
    
    void add_line(int n1, int n2, string arrow_label){
        // if n1 or n2 does not exist - do nothing
        if(n1 < 0 || n2 < 0 || n1 >= nodes.size() || n2 >= nodes.size()) return;
        // ensure that n1 <= n2
        int temp = n1;
        if(n1 > n2) {
            n1 = n2;
            n2 = temp;
        };
        
        multimap<int, pair<int, string> >:: iterator p;
        pair<int, string> p3;
        for(p = lines.begin(); p != lines.end(); p++){
            p3 = p->second;
            // if line with that label already exists - do nothing
            if(p->first == n1 && p3.first == n2 && p3.second == arrow_label) return;
        }
        // line n1 -> n2, arrow_label has not been found
        lines.insert(pair<int, pair<int, string> >(n1, pair<int, string>(n2, arrow_label)));
    }
    
    //--- print json for Graph objects
    void print_graph_json(){
        JSON<< endl<< "{\"GRAPH\":["<< "\""<< title<< "\",";
        char comma = ' ';
        
        // print node list
        JSON<< "\n [";
        for(int i = 0; i < nodes.size(); i++){
            JSON<< comma<< "["<< i <<", \""<< nodes[i] <<"\"] ";
            comma = ',';
        }
        JSON<< "],";
        
        // print arrow list
        comma = ' ';
        JSON<<  "\n [";
        multimap<int, pair<int, string> >::iterator p2;
        for(p2 = arrows.begin(); p2 != arrows.end(); p2++){
            JSON<< comma<< "["<< p2->first << ','<<(p2->second).first << ",\""<<
                    (p2->second).second << "\"]";
            comma = ',';
        }
        JSON<< "],";

        // print line list
        comma = ' ';
        JSON<<  "\n [";
        for(p2 = lines.begin(); p2 != lines.end(); p2++){
            JSON<< comma<< "["<< p2->first << ','<<(p2->second).first << ",\""<<
            (p2->second).second << "\"]";
            comma = ',';
        }
        JSON<< "] ]}";
    }
};// end graph_object class
//====================================================================
template <class tuple_class> class table_object {
public:
    string title;  
    vector <tuple_class> table_contents;
    // constructor
    table_object(){ title = " "; }
    
    void clean(){
        table_contents.clear();
    }
    //--- print json for Table objects
    void print_table_json(){
        /*
        JSON<< endl<< "{\"REPORT\":["<< "\""<< title<< "\"";
        vector<string>::iterator p;
        for(p = report_contents.begin(); p != report_contents.end(); p++){
            JSON<<",\"" <<  *p<< "\"";
        }
        JSON<<"]}"<< endl;
         */
    }
}; // end table_object class