/***************************************************************************
 *   Copyright (C) 2005 by Andreas Pokorny                                 *
 *   andreas.pokorny@biozentrum.uni-wuerzburg.de                           *
 *                                                                         *
 *   This file is part of profdist and cbcanalyzer                         *
 *                                                                         *
 *   Both profdist and cbcanalyzer are free software; you can redistribute * 
 *   it and/or modify it under the terms of the GNU General Public License * 
 *   as published by the Free Software Foundation; either version 2 of the * 
 *   License, or (at your option) any later version.                       *
 *                                                                         *
 *   Profdist and cbcanalyzer are distributed in the hope that it will be  *
 *   useful, but WITHOUT ANY WARRANTY; without even the implied warranty   *
 *   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the      *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#include <string>
#include <stdexcept>
// File is included by aligncode header

template<typename IteratorT>
void AlignCode::read_sequences( std::list<sequence<IteratorT> > const& seq ) 
{
  using namespace std;
  typedef sequence<IteratorT> sequence_t;
  typedef typename list<sequence<IteratorT> >::const_iterator const_it;
  typedef typename list<typename sequence<IteratorT>::string_range>::const_iterator range_it;
  
  size_t num_seq = seq.size();  // first sequence is stored seperate

  // get length of sequences: - 
  size_t max_length = 0;
  for( const_it b = seq.begin(), e = seq.end(); b != e; ++b )
  {
    if( max_length && max_length != b->sequence_length )
      throw runtime_error("Alignment broken, sequences have different size");
    max_length = max( max_length, b->sequence_length  );
  }

  // clear and resize
  clear_resize( num_seq, max_length);



  size_t i = 0;
  for( range_it r_it = seq.begin()->sequence_data.begin(), r_e = seq.begin()->sequence_data.end(); r_it != r_e ; ++r_it )// for every sequence string subset,in the first string 
    for( typename sequence_t::iterator it = r_it->first; i != max_length && it != r_it->second; ++it,++i ) // convert and copy each site
      reference_sequence[i] = mapper.dna2code[*it];

  while( i != max_length )
      reference_sequence[i++] = mapper.dna2code['-'];


  // refill or throw on non complete first sequence !?

  // Getting sequence names, and creating differences to reference sequence
  {
    i = 0;
    // walk through every sequence
    for( const_it it = seq.begin(), e = seq.end(); it != e; ++it, ++i )
      sequence_names[i] = string(it->id.first, it->id.second ); // make a copy of the name 
    
    // skipping first sequence:
    i = 0;
    for( const_it it = ++(seq.begin()), e = seq.end(); it != e; ++it, ++i )
    {
      size_t position = 0; // variable to track current position
      for( range_it r_it = it->sequence_data.begin(), r_e = it->sequence_data.end(); r_it != r_e ; ++r_it ) // and every sequence_t string subset
      {
        for( typename sequence_t::iterator it = r_it->first; position != max_length && it != r_it->second; ++it,++position )  // check if sequences differ:
        {
          if( mapper.dna2code[*it] != reference_sequence[position] ) // then add an entry into alignment_code 
            alignment_codes[i].push_back(a_pair( position, mapper.dna2code[*it] ) );

          // update count matrices
          ++count_matrices[i](reference_sequence[position], mapper.dna2code[*it] );
        }

      }
      const char gap = mapper.dna2code['-'];
      // Add '-' to too short sequences or throw on error?
      while ( position != max_length )
      {
        if( gap != reference_sequence[position] ) // then add an entry into alignment_code 
          alignment_codes[i].push_back(a_pair( position, gap ) );
        // update count matrices
        ++count_matrices[i](reference_sequence[position], gap );
        ++position;
      }

    }
  }

}



template<typename IteratorT>
void read_from_bootstrap( AlignCode & obj, std::list<sequence<IteratorT> > & seq, size_t num_sequences, size_t num_bootstrap, size_t alignment_size ) 
{
  typedef std::list<sequence<IteratorT> > seq_list;
  seq_list temp;
  if( num_bootstrap * alignment_size  == num_sequences ) 
  {
    for( size_t i = 0; i != num_sequences; ++i ) 
    {
      temp.push_back( seq.front() );
      seq.pop_front();
    }
  }
  else {
    temp.push_back( seq.front() );
    seq.pop_front();

    typename sequence<IteratorT>::string_range name = temp.front().id;

    while( !seq.empty() && !compare_range( seq.front().id, name) )
    {
      temp.push_back( seq.front() );
      seq.pop_front();
    }
      
  }
  obj.read_sequences( temp );
} 


