//
//  Fragment_Banks.cpp
//
//
//  Created by Pierre Peterlongo on 25/10/2012
//
#include "Fragment_Bank.h"
extern int size_seeds;
using namespace std;

Fragment_Bank::Fragment_Bank(const char type){extension_type=type;
   
}
Fragment_Bank::~Fragment_Bank(){
    //  hash_delete(seeds, list_of_generic_free);
    //free(seeds_count);
    //  hash_delete(seeds_count, list_of_generic_free);
    all_fragments.clear(); // All the elements of the vector are dropped: their destructors are called, and then they are removed from the vector container, leaving the container with a size of 0.
    // free the array of couples:
}

inline bool startsWith(const char *pre, const char *str)
{
    size_t lenpre = strlen(pre),
    lenstr = strlen(str);
    return lenstr < lenpre ? false : strncmp(pre, str, lenpre) == 0;
}

/**
 * read a file containing starters and their extreme kmers to extend in the following format:
 >1 should have both left (ACTGATG) and right (ATGATGA) extremal kmers in the reads 3 times
 ACTGATGCTGATGATGA
 >extrem_left|id_0|abundance_3|starter_ACTGATG
 ACTGATGCTGATGATGA
 >extrem_right|id_0|abundance_3|starter_ATGATGA
 ACTGATGCTGATGATGA
 >2 should only have right kmer in the reads, with an indel at the first position (2 times TAGTGAT -> T*G*AGTGAT)
 CGTCTAGTGAT
 >extrem_right|id_0|abundance_2|starter_GAGTGAT
 CGTCTAGTGAT
 >3 should only have the left kmer in the reads, with a substitution (2 times CTCTATA -> CTCTGTA)
 CTCTATAGAT
 >extrem_left|id_0|abundance_2|starter_CTCTGTA
 CTCTATAGAT
 */
void Fragment_Bank::load_fragments(char * fragment_file){
    Bank * bank = new Bank(fragment_file);
    char * sequence;
    char * header;
    int size_sequence;
    int size_header;
    
    
    bool not_end_file=bank->get_next_seq(&sequence, &header, &size_sequence, &size_header); // read the first fragment info
    do{

        Fragment new_fragment=Fragment(string(sequence));
        new_fragment.set_comment(string(header));
        not_end_file=bank->get_next_seq(&sequence, &header, &size_sequence, &size_header); // read first extreme kmer
        while(not_end_file){
            if(startsWith("extrem", header)){
                if(startsWith("extrem_left", header)) {
                    // add the reverse complement of the kmer (extend left)
                    revcomp(sequence, strlen(sequence));
                    new_fragment.add_left_extreme_kmer(sequence);
                }
                if(startsWith("extrem_right", header)) new_fragment.add_right_extreme_kmer(sequence);
                not_end_file=bank->get_next_seq(&sequence, &header, &size_sequence, &size_header); // read next extreme kmer or next starter or end of file
                
            }
            else {
                break; // we read the next starter
            }
        } // end of a starter or of the file
        all_fragments.push_back(new_fragment);
    }while(not_end_file);
    delete bank;
}



//////////////////////////////////////////// EXTENTIONS ///////////////////////////////////////////////////
void Fragment_Bank::perform_extensions(const string prefix, int max_graph_depth,int max_nodes, parcours_t search_mode ){ //
    for (vector<Fragment>::iterator it=all_fragments.begin(); it!= all_fragments.end(); ++it){
        it->perform_extension(prefix, max_graph_depth, extension_type, max_nodes, search_mode );
    }
}




void  Fragment_Bank::format_results(const int extension_type, string prefix_name){
    bool is_graph;
    if(extension_type==3 || extension_type==4) is_graph=true;
    else is_graph = false;
    
    if(is_graph){
        id_els first_id_els = {};
        printf("creation of the graph %s\n", prefix_name.c_str());
        GraphOutput graph = GraphOutput(prefix_name); 
        for(int i=0; i<all_fragments.size();i++){
            graph.print_starter_head(i, (char*) all_fragments[i].fragment_sequence.c_str());
            all_fragments[i].fragment_output_graph(graph);
            graph.print_starter_end();
        }
        graph.close();
    }
    else{
        string starter_head;
        bool erase = true;
        for(int i=0; i<all_fragments.size();i++){
            all_fragments[i].fragment_output_sequence(i, prefix_name+string(".fasta"), erase);
            erase = false;
        }
    }
}
