#include "carl_engine.h"
#include <stdio.h>

/* 
This code was written by Keir Lauritzen
*/

using namespace std;

extern "C" void destroy_all();

void make_c_arrays(vector<string> fields, string record, char**& cfields, int*& cfield_len){
    int n_fields = fields.size()+1;
    //cout << n_fields << '\n';
    cfields = (char **) malloc(sizeof(char *) * n_fields);
    cfield_len = (int*) malloc(sizeof(int) * n_fields);

    int n_char = record.size()+1;
    cfields[0] = (char*) malloc(sizeof(char) * n_char);
    cfield_len[0] = n_char;
    record.copy( cfields[0],record.size() );
    cfields[0][n_char-1]='\0';
    
    int i = 1;    
    for (string field : fields){
        n_char = field.size()+1;
        cfields[i] = (char*) malloc(sizeof(char) * n_char);
        cfield_len[i] = n_char;
        field.copy( cfields[i],field.size() );
        cfields[i][n_char-1]='\0';
        ++i;
    }
    return;
}

void print_c_arrays(int len, char** cfields, int* cfield_len){
    for (int i = 0; i < len; i++){
        for (int j = 0; j < cfield_len[i]; j++)
            cout << cfields[i][j];
        cout << '\n';
    }
    return;
}

void delete_c_arrays(int len, char** cfields, int* cfield_len){
    for (int i = 0; i < len; i++){
        free(cfields[i]);
    }
    free(cfields);
    free(cfield_len);
}

vector<string> generate_fields(string record) {
    vector<string> fields;    
    string field = "";
    for (auto r : record){
        if (r != FS)
            field.push_back(r); 
        else {
            if (field.size() > 0) {
                fields.push_back(field);
                field.clear();
            }
        }
    }
    fields.push_back(field); // No terminator on the last field
    return fields;
}

int main(int argc, char *argv[] ){
    if (argc == 1) {
        cout<< "No filename provided.\n" << '\n';
        return 0;
    }
    __init();
    ifstream ifs(argv[1]);
    if (!ifs) {
        cout << "Couldn't open file: " << argv[1] << '\n';
        throw;
    }
    
    for (int i = 0; i < NPAT; ++i){
        ifs.clear();         //http://www.cplusplus.com/forum/beginner/30644/
        ifs.seekg(0, ios::beg);
        
        //cout<< "Before string" << '\n';
        //printf("%s\n", __patterns[i]);
        //cout << __patterns[i] << '\n';
        string pat (__patterns[i]);
        
        
        if (!pat.compare("BEGIN")){
            if (i != 0)
                throw "BEGIN must be first pattern";
          //cout<< "Before action" << '\n';
          (*__actions[i])(0, NULL, NULL); 
        }
        else if (!pat.compare("END")) {
            if (i != NPAT-1)
                 throw "END must be last pattern";
            (*__actions[i])(0, NULL, NULL);
        }
        else {
            for(string record; getline(ifs, record, RS); ){
                vector<string> fields = generate_fields(record);
                
                int len = fields.size()+1;
                char **cfields;
                int *cfield_len;
                make_c_arrays(fields, record, cfields, cfield_len);
                //print_c_arrays(len, cfields, cfield_len);

                regex expr{pat};
                
                if (regex_search(record, expr)){
                    (*__actions[i])(len, cfields, cfield_len); 
                }
                delete_c_arrays(len,cfields,cfield_len);   
            }
        } 
    }
    //delete_pattern_actions();
    destroy_all();
    return 0;
}
