/***************************************************************************
 *   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.             *
 ***************************************************************************/
#ifndef PROFDIST_DISTANCE_INCLUDED_H
#define PROFDIST_DISTANCE_INCLUDED_H
#include "aligncode.h"
#include "profile.h"
#include "progress_update.h"
#include "concepts.h"
#include "types.h"

namespace profdist {
/**
 * @brief Calculates distance between
 * @param[in]  source Alignment source, is not modified by that function
 * @param[out] matrix distance matrix 
 * @param[in]  Q ratenmatrix 
 * @param[in]  model correction model to use
 * @param[in]  expmType 
 * @param[in]  fMax
*/
void compute_distance( AlignCode const& source, profdist::distance_matrix & matrix, profdist::rate_matrix const& Q, profdist::CorrectionModel model, profdist::ExpMType expmType, profdist::FZero fMax );
/**
 * @brief Calculates distance between
 * @param[in]  source Alignment source, is not modified by that function
 * @param[out] matrix distance matrix 
 * @param[in]  Q ratenmatrix 
 * @param[in]  model correction model to use
 * @param[in]  expmType 
 * @param[in]  fMax
 * @param[in]  prg  to display status info on the commandline or within guis
*/
void compute_distance( AlignCode const& source, profdist::distance_matrix & matrix, profdist::rate_matrix const& Q, profdist::CorrectionModel model, profdist::ExpMType expmType, profdist::FZero fMax, ProgressSink& prg );

/**
 * @brief Calculates distance between
 * @param source Profile source, is not modified by that function
 * @param matrix distance matrix 
 * @param Q ratenmatrix 
 * @param model correction model to use
 * @param expmType 
 * @param fMax
 * @param destination the destination, 
*/
void compute_distance( Profile const& source, profdist::distance_matrix & matrix, profdist::rate_matrix const& Q, profdist::CorrectionModel model, profdist::ExpMType expmType, profdist::FZero fMax );
/**
 * @brief Calculates distance between
 * @param[in] source Profile source, is not modified by that function
 * @param[out] matrix distance matrix 
 * @param[in] Q ratenmatrix 
 * @param[in] model correction model to use
 * @param[in] expmType 
 * @param[in] fMax
 * @param[in] prg  to display status info on the commandline or within guis
 * @param destination the destination, 
*/
//void compute_distance( Profile const& source, distance_matrix & matrix, rate_matrix const& Q, CorrectionModel model, ExpMType expmType, FZero fMax, ProgressSink& prg );

/**
 * \brief Computes the distance by countng compensatory base changes.
 * The user has to supply a cbc detector, which implements the concept described 
 * by CbcDetector \see CbcDetector.
 * \param[in] source
 * \param[out] matrix
 * \param[in] detect
 */
template<typename IteratorT, typename Detector>
void compute_distance( sequence_data< brace_fold_data< num_sequences<base_adaptor<IteratorT> > > > const& source, distance_matrix & matrix, Detector const& detect );


/**
* \brief Prints matrices in phylip format into an ostream. 
* 
* \param[in] out
* \param[in] matrix
* \param[in] begin
* \param[in] end
* \param[in] WellFormated default value is true
*/
template<typename IteratorT>
std::ostream& print_distance_matrix( std::ostream& out, distance_matrix const& matrix, IteratorT begin, IteratorT end, bool FixedPoint = false, bool WellFormated = true  );

/**
* \brief Prints matrix as tsv format
* tsv stands for tab separated values. 
* \param[in] out
* \param[in] matrix
* \param[in] begin
* \param[in] sep  tab separator by default
* \param[in] end
* \param[in] FixedPoint if false scientific notation will be used
*/
template<typename IteratorT>
std::ostream& print_distance_matrix_tsv( std::ostream& out, distance_matrix const& matrix, IteratorT begin, IteratorT end, char sep = '\t', bool FixedPoint = false);


/**
 * Reads an arbitrary sized distance matrix from the istream, and writes all names found into 
 * begin.
 * \param[in] in
 * \param[out] out 
 * \param[in] begin insert iterator which should insert the names found by this routine 
 */
template<typename InsertIteratorT>
std::istream& read_distance_matrix( std::istream& in, distance_matrix & matrix, InsertIteratorT begin );

std::istream& read_distance_matrix( std::istream& in, profdist::distance_matrix & matrix);

/**
 * reads a rate_matrix from the istream
 * \param[in] in
 * \param[out] out 
 */
std::istream& read_rate_matrix( std::istream& in, profdist::rate_matrix & matrix );


}

#include "distance.inl"

#endif

