#include <iostream>
#include <vector>
#include "Starter.h"
#include "Extension_Bank.h"
#include "BooleanVector.h"

extern "C"{
  //#include "read_coherence_mapsembler/simplehash.h"
#include "read_coherence_mapsembler/couple.h"
#include "read_coherence_mapsembler/list.h"
#include "read_coherence_mapsembler/hash.h"
}
#include "commons.h"
#include "../minia/Bank.h"

#ifndef _FRAGMENT_BANK_H
#define _FRAGMENT_BANK_H

/**
 * A set of indexible fragments
 */
class Fragment_Bank{
 public: 
  /**
   * All fragments stored in the set
   */
  vector<Fragment_Starting*> all_fragments;
    

  /**
   * Stores all seeds info.
   * an entry = a couple (fragment_id, position on the fragment)
   * The seeds_count table enables for each seed to know were it starts and how many occurrences one has
   */
  couple *seed_table;

  /**
   * total number of stored seeds (size of seed_table)
   */
  uint64_t total_seeds;

  /**
   * seeds from the fragments. key = seed, value=number of occurrences.
   */
  hash_t seeds_count;
  /**
   * Create the seeds hash table
   */
  Fragment_Bank();
  /**
   * Free all fragments, delete the hash table
   */
  ~Fragment_Bank();
  
  /**
   * Given a size of seeds (in common.h), all clean seeds (with only A,C,G,T) of size size_seeds are indexed in the hash table
   */
  void index_fragments_and_init_vector();
  
  /**
   * Read fragments from a file, and load them in the set of fragments
   */
  void load_fragments(char * fragment_file);
  
  /**
   * Map a set of reads from files (managed in Bank) on fragments
   */
  void map_reads(Bank * reads, const int substitutions_allowed);
  
  /**
   * For debug: show the reads aligning a fragment
   */
  void show_alignments();
    
    /**
     * Outputs in output_file_name the mapped reads
     */
    void output_mapped_reads(const char * output_file_name);

 void fragment_mapped (Bank * reads, char * read, int size_read, vector<int> already_tested , const int substitutions_allowed, int param_hash);
  
 private:  
  /**
   * Given a seed, a fragment and a position, make the indexation
   */
  void index_one_seed(const char * seed, const int fragment_id, const int position_on_fragment);
    
    
    /**
     * used to mark a position in nodes, for instance to know if it has been already tested with seed
     */
    BooleanVector * bv;
    /**
     * test if a position has already been tested (for instance an anchoring position of a mapped read)
     */
    bool is_position_already_tested(const Fragment_Starting * fragment, int pos);
    /**
     * set a position has already been tested (for instance an anchoring position of a mapped read)
     */
    void set_position_tested(const Fragment_Starting * fragment, int pos);
};
  
#endif // _FRAGMENT_BANK_H
