// This file is part of necsim project which is released under MIT license.
// See file **LICENSE.txt** or visit https://opensource.org/licenses/MIT) for full license details.
//
/**
 * @file ProtractedTree.cpp
 * @brief Contains the ProtractedTree class for running simulations and outputting the phylogenetic trees using protracted
 * speciation.
 *
 * Contact: samuel.thompson14@imperial.ac.uk or thompsonsed@gmail.com
 * @copyright <a href="https://opensource.org/licenses/MIT"> MIT Licence.</a>
 */

#include "ProtractedTree.h"
namespace necsim
{
    bool ProtractedTree::calcSpeciation(const long double &random_number, const long double &speciation_rate,
                                        const unsigned long &no_generations)
    {
        if(generation < speciation_generation_min)
        {
            return false;
        }
        if(generation >= speciation_generation_max)
        {
            return true;
        }
        return checkSpeciation(random_number, speciation_rate, no_generations);
    }

    void ProtractedTree::speciateLineage(const unsigned long &data_position)
    {
        (*data)[data_position].setSpec(0.0);
        if(speciation_generation_min >= (*data)[data_position].getGenerationRate() + (*data)[data_position].getGeneration())
        {
            (*data)[data_position].setGenerationRate(static_cast<unsigned long>(floor(speciation_generation_min)) + 2);
        }
#ifdef DEBUG
        if(generation < speciation_generation_min)
        {
            (*data)[data_position].logLineageInformation(50);
            throw FatalException("Speciation attempted before minimum speciation generation. Please report this bug.");
        }
#endif // DEBUG
        (*data)[data_position].speciate();
    }

    bool ProtractedTree::getProtracted()
    {
        return true;
    }

    void ProtractedTree::setProtractedVariables(double speciation_gen_min_in, double speciation_gen_max_in)
    {
        speciation_generation_min = speciation_gen_min_in;
        speciation_generation_max = speciation_gen_max_in;
    }

    string ProtractedTree::getProtractedVariables()
    {
        stringstream ss;
        ss << speciation_generation_min << "\n" << speciation_generation_max << "\n";
        return ss.str();
    }

    double ProtractedTree::getProtractedGenerationMin()
    {
        return speciation_generation_min;
    }

    double ProtractedTree::getProtractedGenerationMax()
    {
        return speciation_generation_max;
    }

    string ProtractedTree::protractedVarsToString()
    {
        string tmp = "1 , " + to_string(speciation_generation_min) + ", " + to_string(speciation_generation_max);
        return tmp;
    }
}