#ifndef INDIVIDUAL_H
#define INDIVIDUAL_H

#include <iostream>
#include <string>
#include <vector>

#include "specie.h"
#include "genome.h"

class mClock;
class species;

using indId = unsigned int;

/*#include "../include/individual.h"
#include "../include/population.h"
#include "../include/cell.h"


SEX SPECIE AGE AGE_CLASS FITNESS TRAITS
*/


// TODO: smart pointers uniq_ptr everywhere (umap)
// Individual must be refered to from it id



class individual
{
    public:
        individual(individual& mother, individual& father, mClock &m_clock, species* spe);
        individual(int p_age, vector<int> p_genome);

        ~individual();


        void print_all();
        unsigned int gen_val(int location);
        unsigned int gen_size();
        //individual(int * g_seq, species * h_species, int m_age);
        //individual(individual pere, individual mere);
        //void gprint();
        //species * get_species();
        //genome * get_genome();
        //double calc_trait(int trait_number);
        int get_birth();
        valarray<int> get_subGenome(valarray<bool> * mask);
        vector<int> get_genome();
        valarray<int> get_genome_va();
        vector<int>& get_genome_ref() { return genome; }
        
        
        int age_update(mClock &m_clock, species * pSpe);
        void mutate(species * pSpecie);
        void mutate_pos(int nAll, int pos);
        
        indId get_id();
        
        //TEST FUNCTION
        int check_integrity(species * pSpe);
        

        static indId counter_created;
        static indId counter_alive;
        const indId id;

        int get_age();

    protected:
    private:


        double age; //DEPRECATED?
        unsigned int birth_date;
        vector<int> genome;  // !!!!! USE VALARRAY, make it public?



};


inline unsigned int individual::gen_val(int location)
{
    return genome.at(location);
}

inline unsigned int individual::gen_size()
{
    return genome.size();
}


inline int individual::get_age()
{
    return age;
}


inline int individual::get_birth()
{
    return birth_date;
}

inline indId individual::get_id()
{
    return id;
}


#endif // INDIVIDUAL_H
