// $Id: individual.h,v 1.22 2018/01/03 21:33:03 mkkuhner Exp $

/*
Copyright 2002-2005 Mary K. Kuhner, Peter Beerli, and Joseph Felsenstein

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

*/

/* Authors: Peter Beerli, Mary Kuhner, Jon Yamato and Joseph Felsenstein */


// This file defines the class that stores "individual" specific information.

#ifndef INDIVIDUAL_H
#define INDIVIDUAL_H

#include <vector>
#include <string>
#include <map>

#include "haplotypes.h"
#include "types.h"                      // for Branch_ptr declaration
#include "vectorx.h"

//------------------------------------------------------------------------------------

class Branch;
class Random;
class DLCell;

//------------------------------------------------------------------------------------

class Individual
{
  private:
    long               m_id;
    LongVec2d          m_phasemarkers; // dim:  loci by markers
    LongVec2d          m_phasesites;   // dim:  loci by sites (for XML output)
    string             m_name;
    vector<Branch_ptr> m_ptips;

    std::map<std::pair<string, long>, Haplotypes> m_haplotypesmap;
    std::map<std::pair<string, long>, vector<LocusCell> > m_currentHapsMap;
    // The string is the name of the locus, and the long is the marker (will
    //  almost always just be 0, but might not be).

  public:
    Individual()                                  {};
    ~Individual()                                 {};
    //We accept the default for:
    //Individual& operator=(const Individual& src);
    //Individual(const Individual& src);

    string          GetName()         const       { return m_name; };
    vector<Branch_ptr> GetAllTips()   const       { return m_ptips; };
    StringVec1d     GetAllTipNames()  const;
    long            GetId()           const       { return m_id; };
    const LongVec2d& GetPhaseMarkers() const      { return m_phasemarkers; };
    const LongVec2d& GetPhaseSites() const        { return m_phasesites; };
    bool            AnyPhaseUnknownSites() const;
    bool            MultipleTraitHaplotypes() const;

    void            PruneSamePhaseUnknownSites();
    std::pair<long,long> PickRandomPhaseMarker(Random& rs) const;
    std::pair<string,long> PickRandomHaplotypeMarker() const;

    void SetPhaseMarkers(const LongVec2d& pm);
    void SetPhaseSites(const LongVec2d& ps);
    void SetName(const string& newname)           { m_name = newname; };
    void SetTips(vector<Branch_ptr> tps)          { m_ptips = tps; };
    void AddTip(Branch_ptr tip)                   { m_ptips.push_back(tip); };
    void SetId(long newid)                        { m_id = newid; };
    void AddHaplotype(long regnum, string lname, long marker, const StringVec1d& alleles, double penetrance);
    StringVec1d GetAllelesFor(string lname, long marker) const; //phase 1
    vector<LocusCell> GetLocusCellsFor(string lname, long marker) const; //phase 2
    Haplotypes GetHaplotypesFor(string lname, long marker) const;
    string GetMarkerDataFor(string lname, long marker) const; //phase 3/Output.
    void ChooseNewHaplotypesFor(string lname, long marker);
    bool ChooseRandomHaplotypesFor(string lname, long marker);
    void RandomizeAllHaplotypes();

    void ChooseFirstHaplotypeFor(string lname, long marker);
    bool ChooseNextHaplotypeFor(string lname, long marker);

    // For simulated data.
    void SetHaplotypes(string lname, long marker, Haplotypes haps);
    StringVec1d GetAllelesFromDLs(long locus, long marker, bool moving, DataModel_ptr model);

    bool IsValidIndividual() const;
    StringVec1d GetTraitXML(long nspaces) const;

    // Debugging function.
    void PrintHaplotypesFor(string lname, long marker) const;

};

//------------------------------------------------------------------------------------

typedef vector<Individual> IndVec;

//------------------------------------------------------------------------------------

#endif // INDIVIDUAL_H

//____________________________________________________________________________________
