/***************************************************************************
 *   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 "forester_parser.h"

#if 0
void parse_forester( std::string const& filename, std::list<file_sequence>& sequences )
{
  using namespace boost::spirit;
  typedef char char_t;
  typedef position_iterator<file_iterator<char_t> > iterator_t;
  file_iterator<char_t> file_handle( filename );

  if (!file_handle)
    throw std::runtime_error( ("Unable to open file " + filename) );

  
  iterator_t first( file_handle, file_handle.make_end(), filename );
  iterator_t end( file_handle.make_end(), file_handle.make_end(), filename );


  forester_grammar grammar( sequences ); 
#ifdef BOOST_SPIRIT_DEBUG
  BOOST_SPIRIT_DEBUG_NODE(grammar);
#endif 
  // Define your rule

  boost::spirit::parse_info<iterator_t> info = boost::spirit::parse( first, end, grammar);
  if( !info.full )
  {
    std::ostringstream out;
    out << "Parsing failed at line " << info.stop.get_position().line << " and column " 
      << info.stop.get_position().column << " in file " << info.stop.get_position().file 
      << '\n' << sequences.size() << " Sequences were found.\nError happened near:\n[...]" 
      << std::string( std::max( first, info.stop - 20 ), info.stop) << '\n';
    throw std::runtime_error( out.str() );
  }
}
#endif

#include <iostream>
#include <fstream>

void parse_forester( std::string const& filename, std::list<file_sequence>& sequences )
{
  using namespace boost::spirit;
  typedef position_iterator<const char*> iterator_t;
  
  std::ifstream in(filename.c_str());
  
  if (!in)
    throw std::runtime_error( ("Unable to open file " + filename) );
  
  in.seekg(0, std::ios::end);
  size_t size = in.tellg();
  in.seekg(0, std::ios::beg);
  
  char* data = new char[size + 1];
  in.read(data, size);
  data[size] = 0;
  
  iterator_t first( data, data + size, filename );
  iterator_t end( data + size, data + size, filename );


  forester_grammar grammar( sequences ); 
#ifdef BOOST_SPIRIT_DEBUG
  BOOST_SPIRIT_DEBUG_NODE(grammar);
#endif 
  // Define your rule

  boost::spirit::parse_info<iterator_t> info = boost::spirit::parse( first, end, grammar);
  if( !info.full )
  {
    std::ostringstream out;
    out << "Parsing failed at line " << info.stop.get_position().line << " and column " 
      << info.stop.get_position().column << " in file " << info.stop.get_position().file 
      << '\n' << sequences.size() << " Sequences were found.\nError happened near:\n[...]" 
      << std::string( std::max( first, info.stop - 20 ), info.stop) << '\n';
	delete [] data;
    throw std::runtime_error( out.str() );
  }
  
  delete [] data;
}

void parse_forester(const char* data_begin,
                    const char* data_end,
                    std::list<file_sequence>& sequences)
{
  using namespace boost::spirit;
  typedef position_iterator<const char*> iterator_t;


  iterator_t first( data_begin, data_end );
  iterator_t end( data_end, data_end );


  forester_grammar grammar( sequences );
#ifdef BOOST_SPIRIT_DEBUG
  BOOST_SPIRIT_DEBUG_NODE(grammar);
#endif
  // Define your rule

  boost::spirit::parse_info<iterator_t> info = boost::spirit::parse( first, end, grammar);
  if( !info.full )
  {
    std::ostringstream out;
    out << "Parsing failed at line " << info.stop.get_position().line << " and column "
      << info.stop.get_position().column << " in file " << info.stop.get_position().file
      << '\n' << sequences.size() << " Sequences were found.\nError happened near:\n[...]"
      << std::string( std::max( first, info.stop - 20 ), info.stop) << '\n';
    throw std::runtime_error( out.str() );
  }
}


#ifdef FORESTER_TEST
#include <iostream>

int main( int argc, char ** argv )
{
 
  if( argc != 1 )
  {

    std::list<file_sequence> seqs;
    try {
    parse_forester( argv[1], seqs );
    }
    catch( std::runtime_error & e )
    {
      std::cout << e.what();
      return 1;
    }

    for( std::list<file_sequence>::const_iterator it = seqs.begin(), e = seqs.end();
        it != e; ++it)
    {
      std::cout << "ID:" << std::string(it->id.first, it->id.second) << std::endl;
      std::cout << "CLASSIFCATION:" << std::endl;
      for( std::list<file_sequence::string_range>::const_iterator _it = it->classification.begin(),
          _e = it->classification.end();
          _it != _e; ++_it )
        std::cout << '|' << std::string(_it->first, _it->second ) << "|";
      std::cout << std::endl << "SEQUENCE:" << std::endl;
      for( std::list<file_sequence::string_range>::const_iterator _it = it->sequence_data.begin(),
          _e = it->sequence_data.end();
          _it != _e; ++_it )
        std::cout << '|' << std::string(_it->first, _it->second ) << "|";
      std::cout << std::endl;
      std::cout << std::endl << "Folding:" << std::endl;
      for( std::list<file_sequence::string_range>::const_iterator _it = it->char_fold_data.begin(),
          _e = it->char_fold_data.end();
          _it != _e; ++_it )
        std::cout << '|' << std::string(_it->first, _it->second ) << "|";

      std::cout << std::endl;
    }
  }
  else 
    std::cout << "Add a file name to the command to test the forester parser" << std::endl;
}


#endif

