// $Id: region.h,v 1.55 2018/01/03 21:32:58 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 */


// Region--a storage class, containing data information that applies
//    to the genetic info of that region (regional quick theta estimate,
//    number of tips, region name).
//
//    In addition, Region serves as the bridge between the data and the
//    tree via Region::CreateTree().  CreateTree() copies the prototype
//    tree and finishes tree construction (creates the tips and individuals,
//    sets the site ranges) and enables data likelihood calculation (creates
//    the data likelihood calculator).  It returns an owning pointer to
//    the newly created tree.
//
// Written by Jim Sloan, heavily revised by Jon Yamato
// 2002/01/03 changed Tipdata::data to a vector for generality--Mary Kuhner
// 2002/07/25 split out Locus class -- Mary Kuhner

#ifndef REGION_H
#define REGION_H

#include <cassert>                      // May be needed for inline definitions.
#include <string>
#include <vector>

#include "argtree.h"
#include "constants.h"
#include "forceparam.h"                 // for return type of GetScalars()
#include "individual.h"                 // for IndVec typedef
#include "locus.h"                      // for TipData and for Locus member
#include "newick.h"                     // for UserTree member, m_usertree;
#include "toxml.h"                      // for SampleXML/IndividualXML/PopulationXML in Region::MakePopXML()
#include "types.h"
#include "vectorx.h"

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

class Tree;
class MapCollector;

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

class Region
{
  private:

    Region(const Region& src);             // not defined
    Region& operator=(const Region& src);  // not defined

    IndVec             m_individuals;
    vector<Locus>      m_loci;
    vector<Locus>      m_movingloci;       // either 'floating' or 'jumping'.
    string             m_regionname;
    long               m_id;               // region number
    UserTree*          m_usertree;         // we own this! - this is the Newick tree if read in
    double             m_effpopsize;
    std::set<long int> m_ploidies;         // Phase 1 only.
    bool               m_snppanel;

    // utility functions
    bool         MultiSampleIndividuals() const;
    Individual&  GetIndividual(long n);
    bool         ValidLocus(long locus) const;
    bool         ValidMovingLocus(long locus) const;
    StringVec1d  MakeTraitsXML(unsigned long nspaces) const;
    StringVec1d  MakePopXML(unsigned long nspaces) const;

  public:

    bool         RecombinationCanBeEstimated() const;
    Region(std::string rname) : m_regionname(rname), m_usertree(new NullUserTree()),
                                m_effpopsize(1.0) {};
    ~Region()    { delete m_usertree; };

    // Add a new Locus
    void AddLocus(bool movable=false, string name="");

    // ARGtree storage for phase 2
    vector<ARGEdge> m_argedges;      // ARG tree, public so parsetreetodata can mess with it
    void AddARGEdge(ARGEdge edge){m_argedges.push_back(edge);};

    //Save ploidy (used for trait stuff)
    void AddPloidy(long ploid) {m_ploidies.insert(ploid);};

    // Access
    void AddIndividual(const Individual& newind) {m_individuals.push_back(newind);};
    void SetID(long newid)                       {m_id = newid; };
    void SetUserTree(UserTree* utree)            {delete m_usertree; m_usertree = utree;};
    void SetSnpPanel(bool val)                   {m_snppanel = val;};
    bool GetSnpPanel()                           {return m_snppanel;};

    //Phase 1 to Phase 2 functions:
    void SetEffectivePopSize(double newsize)     {m_effpopsize = newsize; };
    void InitializeRegionalMapPositionsUsingGlobalMapPositions();
    void SetupAndMoveAllLoci();
    void MakeAllMovableLociMove();

    //Phase 2 to Phase 1 function:
    void RevertMovingLoci();

    // Forwarders to Locus class; used by xml.cpp
    void SetNmarkers(long locus, long n);
    void SetGlobalMapPosition(long locus, long n);
    void SetName(long locus, std::string name);
    void SetOffset(long locus, long n);
    void SetPositions(long locus, const LongVec1d& pos);
    void SetPositions(long locus); // set to defaults
    void SetNsites(long locus, long numsites);
    void SetDataType(long locus, const DataType_ptr dtype);
    void SetTipData(long locus, const TipData& td);

    //Forwarder to individuals; used by parsetreetodata.cpp
    void SetPhaseMarkers(long indnum, LongVec2d& phases);

    // Potentially expensive Forces::QuickCalc() helper functions
    LongVec1d    CalcNVariableMarkers() const;  // dim: by xpart

    //Getter functions
    long         GetID()               const {return m_id;};
    double       GetEffectivePopSize() const {return m_effpopsize;};
    long         GetNIndividuals()     const {return m_individuals.size();};
    const Individual& GetIndividual(long n) const {return m_individuals[n];};
    string       GetRegionName()       const {return m_regionname;};
    Locus&       GetLocus(long locus)        {assert(ValidLocus(locus)); return m_loci[locus]; };
    const Locus& GetLocus(long locus)  const {assert(ValidLocus(locus)); return m_loci[locus]; };
    const Locus& GetMovingLocus(long mloc) const {assert(ValidMovingLocus(mloc)); return m_movingloci[mloc];}
    const IndVec& GetIndividuals() const {return m_individuals;};
    bool         HasLocus(string lname)const;
    const Locus& GetLocus(string lname)const;
    long         GetLocusIndex(string lname) const;
    long         GetNloci()            const {return m_loci.size(); };
    long         GetNumAllLoci()const;
    long         GetNumFixedLoci()const;
    long         GetNumMovingLoci()    const {return m_movingloci.size();};
    long         GetNumSites() const;
    rangepair    GetSiteSpan() const;
    void         MakeUserTree(Tree* treetips);
    bool         HasUserTree() const;
    StringVec1d  ToXML(unsigned long nspaces) const;
    DoubleVec1d  GetMuRatios()         const;
    std::set<long int> GetPloidies() const {return m_ploidies;};

    // Forwarders to Locus class
    long         GetNmarkers(long locus)    const {return m_loci[locus].GetNmarkers();};
    long         GetGlobalMapPosition(long locus) const {return m_loci[locus].GetGlobalMapPosition();};
    long         GetOffset(long locus)      const {return m_loci[locus].GetOffset();};
    LongVec1d    GetUserMarkerLocations(long locus)   const {return m_loci[locus].GetUserMarkerLocations();};
    long         GetLocusNsites(long locus)      const;
    StringVec1d  GetAllLociNames()   const;
    StringVec1d  GetAllLociDataTypes() const;
    StringVec1d  GetAllLociMuRates() const;
    DataModel_ptr GetLocusDataModel(long locus)  const {return m_loci[locus].GetDataModel(); };
    long         GetNTips()                 const {return m_loci[0].GetNTips();};
    long         GetNXTips(long xpart)      const;
    vector<TipData> GetAllTipData(long locus)   const {return m_loci[locus].GetTipData();};
    DoubleVec1d  CountNBases() const;
    void         AddUniqueNamesTo(std::set<string>& popnames) const;

    // Factory function
    Tree*        CreateTree();

    // Genotypic-data support functions
    bool         CanHaplotype() const;
    void         PruneSamePhaseUnknownSites(IndVec& indivs) const;
    bool         AnyPhaseUnknownSites() const;

    bool         AnyMapping() const;
    bool         AnyJumpingAnalyses() const;
    bool         AnySimulatedLoci() const;

    bool         AnySNPDataWithDefaultLocations() const;

    // Helper function for original use in DataPack::RemoveUneededPartitions
    void         RemovePartitionFromLoci(force_type);
    void         CopyTipDataForLocus(const string& lname);

    // Helper function for ReportPage(DataPage::Show, echoing data)
    StringVec2d  GetMarkerDataWithLabels() const;  // dim: locus X tip

    // Validity checking
    bool         IsValidRegion(string & errorString) const;
    // helper for parsetreetodata
    bool         IsDuplicateTipName(const string& newname) const;

    //We save the results of mapping in the appropriate loci.
    void SaveMappingInfo(MapCollector* mapcoll);
    void SaveMappingInfo(std::vector<MapCollector*> mapcolls,
                         DoubleVec1d logweights);
    void ReportMappingInfo();
    StringVec2d CreateAllDataModelReports() const;

    //Write out mapping files
    void         WriteAnyMapping() const;

    // These are power-user functions, generally used by our lab in writing
    // simulations; they are not called in normal execution.  They are only
    // used when JSIM is defined:

    // Write a Fluctuate format file.
    void         WriteFlucFile(const string& outfilename, bool onlyregion) const;
    // Break up a multi-population data set into single-population ones
    StringVec2d  MakeByPopXML(unsigned long nspaces) const;
    void         WritePopulationXMLFiles() const;
    void         WriteToXMLFileUsing(std::ofstream& ofile, StringVec1d& region_contents) const;
    void         WriteToXMLFileUsing(std::ofstream& ofile, StringVec2d& region_contents, bool produceonepop) const;

    // Helpers for XML infile creation.
    // vector<ARGNode> GetARGNodes() {return m_argnodes;};

  private:
    std::vector<PopulationXML> MakeVectorOfPopulationXML() const;

};

#endif // REGION_H

//____________________________________________________________________________________
