#include "trait.h"



/*trait::trait(string myName, unordered_map<string, double> myParameters,
             vector<double> myE, vector<double> myZopt,
             vector<ltypes> myTypesIndex, vector<double> mySelInt, bool myNhpp, bool myIndexed)
{
    name = myName;
    parameters = myParameters;
    E = myE;
    cout << "CHECK E " << name << ": ";
    for (int i=0;i<E.size();i++)
    {
        cout << E[i] << " ";
    }
    cout << endl;
    Zopt = myZopt;
    typesIndex = myTypesIndex;
    selInt = mySelInt;
    nhpp = myNhpp;
    indexed = myIndexed;

}*/


trait::trait(string myName, unordered_map<string, double> myParameters,
             unordered_map<int, vector<double>> myTemporalE, unordered_map<int, vector<double>> myTemporalZopt,
             vector<ltypes> myTypesIndex, unordered_map<int, vector<double>> myTemporalSelInt, bool myNhpp, bool myIndexed, double myMeanZ, double myVarEps)
{
    name = myName;
    parameters = myParameters;
    temporalE = myTemporalE;
    temporalZopt = myTemporalZopt;
    temporalSelInt = myTemporalSelInt;

    E = temporalE[1];//get E value at time 1 (first step of the clock)
    Zopt = temporalZopt[1];
    selInt = temporalSelInt[1];
    /*cout << "CHECK E " << name << ": ";
    for (int i=0;i<E.size();i++)
    {
        cout << E[i] << " ";
    }
    cout << endl;*/
    typesIndex = myTypesIndex;
    nhpp = myNhpp;
    indexed = myIndexed;

    meanZ = myMeanZ;
    varEps = myVarEps;
}

trait::~trait()
{
    //Close lua, desallocate all
}

void trait::set_E(unsigned int t)
{
    E = temporalE[t];
    /*for (int i=0;i<E.size();i++)
    {
        cout << E[i] << " ";
    }
    cout << endl;*/
}

void trait::set_Zopt(unsigned int t)
{
    Zopt = temporalZopt[t];
    /*for (int i=0;i<E.size();i++)
    {
        cout << E[i] << " ";
    }
    cout << endl;*/
}

void trait::set_SelInt(unsigned int t)
{
    selInt = temporalSelInt[t];
    /*for (int i=0;i<E.size();i++)
    {
        cout << E[i] << " ";
    }
    cout << endl;*/
}

//Simple sum of each type additive value
double trait::calc_add_value(individual& myInd, double E)
{
    double sum = 0.0;
    //iterate on types & sum values
    for(ltypes& t : typesIndex)
    {
        sum += t.calc_add_value(myInd, E);
        /* DEBUG */ if (std::isnan(abs(t.calc_add_value(myInd, E))))
        /* DEBUG */ {
        /* DEBUG */      cout << "calc_additive_values (trait): nan" << endl;
        /* DEBUG */      exit(0);
        /* DEBUG */ }
        
    }
    return sum;
}

vector<unsigned int> trait::get_loci() // get all involved loci, regardless the ltype
{
    vector<unsigned int> loci;
    for(ltypes& t : typesIndex)
    {
        vector<unsigned int> loci_type = t.get_locList();

        for (unsigned int current_l : loci_type)
        {
            bool already_present_locus = false;
            for (unsigned int old_l : loci)
            {
                if (current_l == old_l)
                {
                    already_present_locus = true;
                }
            }
            if (!already_present_locus)
            {
                loci.push_back(current_l);
            }
        }
        //loci.insert(loci.end(), loci_type.begin(), loci_type.end());
    }
    return loci;
}

vector<vector<unsigned int>> trait::get_loci_by_lt() // get all involved loci, by ltype
{
    vector<vector<unsigned int>> loci;
    for(ltypes& t : typesIndex)
    {
        loci.push_back(t.get_locList());
    }
    return loci;
}
