/* ***************************************************************************
 *
 *                              KisSplice
 *      de-novo calling alternative splicing events from RNA-seq data.
 *
 * ***************************************************************************
 *
 * Copyright INRIA
 *  contributors :  Vincent Lacroix
 *                  Pierre Peterlongo
 *                  Gustavo Sacomoto
 *                  Vincent Miele
 *                  Alice Julien-Laferriere
 *                  David Parsons
 *
 * pierre.peterlongo@inria.fr
 * vincent.lacroix@univ-lyon1.fr
 *
 * This software is a computer program whose purpose is to detect alternative
 * splicing events from RNA-seq data.
 *
 * This software is governed by the CeCILL license under French law and
 * abiding by the rules of distribution of free software. You can  use,
 * modify and/ or redistribute the software under the terms of the CeCILL
 * license as circulated by CEA, CNRS and INRIA at the following URL
 * "http://www.cecill.info".

 * As a counterpart to the access to the source code and  rights to copy,
 * modify and redistribute granted by the license, users are provided only
 * with a limited warranty  and the software's author,  the holder of the
 * economic rights,  and the successive licensors  have only  limited
 * liability.

 * In this respect, the user's attention is drawn to the risks associated
 * with loading,  using,  modifying and/or developing or reproducing the
 * software by the user in light of its specific status of free software,
 * that may mean  that it is complicated to manipulate,  and  that  also
 * therefore means  that it is reserved for developers  and  experienced
 * professionals having in-depth computer knowledge. Users are therefore
 * encouraged to load and test the software's suitability as regards their
 * requirements in conditions enabling the security of their systems and/or
 * data to be ensured and,  more generally, to use and operate it in the
 * same conditions as regards security.
 *
 * The fact that you are presently reading this means that you have had
 * knowledge of the CeCILL license and that you accept its terms.
 */

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <vector>
#include <stack>
#include <utility>
#include <algorithm>
#include "NGraph.h"
#include "Utils.h"

#ifndef MOUTH_ENUMERATION_H
#define MOUTH_ENUMERATION_H

template<class TEdgeFunctor, class TNodeFunctor>
bool read_edges_and_nodes_withoptimIO(char* filename_info, 
				      char* filename_contents_edge, char* filename_contents_node, 
				      char* filename_edge, char* filename_node, 
				      int *required_sequence,
				      TEdgeFunctor edgefunctor, TNodeFunctor& nodefunctor)
{
  ////////////////////////////
  ////////////////////////////
  ////////////////////////////
  // IO optimization (start)
  ////////////////////////////  
  int bcc_size, records_per_file, number_of_files_max, file_index;

  FILE *info_file = fopen(filename_info, "r");
  if (info_file == NULL) { fprintf(stderr, "Problem opening %s!\n", filename_info); exit(0); }
  FILE *contents_file_edge = fopen(filename_contents_edge, "r");
  if (contents_file_edge == NULL) { fprintf(stderr, "Problem opening %s!\n", filename_contents_edge); exit(0); } 
  FILE *contents_file_node = fopen(filename_contents_node, "r");
  if (contents_file_node == NULL) { fprintf(stderr, "Problem opening %s!\n", filename_contents_node); exit(0); }  

  // read the info file 
  fscanf(info_file, "%d \n",&bcc_size );
  fscanf(info_file, "%d \n",&records_per_file );
  // find in which file is the required record
  number_of_files_max = NUMBEROFFILES;
  if (bcc_size<NUMBEROFFILES)
    number_of_files_max = bcc_size;
  file_index = ((*required_sequence-1)/(records_per_file)) + 1;
  if (file_index>number_of_files_max)
    file_index = number_of_files_max;
  if ( (*required_sequence <=0) || (*required_sequence > bcc_size) ) {
    fprintf(stderr, "Problem opening sequence %d in edge/node files !\n", *required_sequence); exit(0); }  

  // filenames
  char total_edge_fname[1024];
  sprintf( total_edge_fname,  "%s_%d",filename_edge,file_index );
  char total_node_fname[1024];
  sprintf( total_node_fname,  "%s_%d",filename_node,file_index );  
  ////////////////////////////
  // IO optimization (end)
  ////////////////////////////
  ////////////////////////////
  ////////////////////////////
  
  FILE* edge_file = open_file(total_edge_fname);
  FILE* node_file = open_file(total_node_fname);

  bool atleast4nodes = read_node_noncontigous_file_withoptimIO<TNodeFunctor>( contents_file_node, node_file, required_sequence, &file_index, nodefunctor);
  if (atleast4nodes){
    read_edge_file_withoptimIO<TEdgeFunctor>( contents_file_edge, edge_file, required_sequence, &file_index, edgefunctor );
  }
  fclose( contents_file_edge );
  fclose( contents_file_node );
  fclose( edge_file );
  fclose( node_file );
  
  return atleast4nodes;
}

//Type used to represent a path.
//It keeps track of the length (distance) of the path, its number of branching nodes and its nodes
struct Path {
    int distance;
    int branchingNodes;
    vector<int> nodes;
    
    Path():distance(0), branchingNodes(0), nodes(){}
    Path (int distance, int branchingNodes, const vector<int> &nodes) : distance(distance), branchingNodes(branchingNodes), nodes(nodes){}
};

#endif /* MOUTH_ENUMERATION_H */
