// $Id: datapack.h,v 1.59 2018/01/03 21:32:57 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 */


// In general, a DataPack owns a container of pointer to Regions, which
// own a container of Locus objects, which own a container of TipData objects.
//
// DataPack--a storage class, with a container of pointers to all
//    Regions programwide.  DataPack owns what the pointers point to.
//    It also tracks some population level data, number of populations
//    and population names.  It does not track any migration specific
//    info (which is handled by class ForceSummary).
//
// Written by Jim Sloan, heavily revised by Jon Yamato
// 2002/01/03 changed Tipdata::data to a vector for generality--Mary Kuhner

// NB  This code distinguishes between "markers" and "sites".  A marker
// is a site for which we have data.  In SNP data, for example, every base
// pair is a site, but only the SNPs are markers.  Data likelihoods are
// calculated on markers; recombination probabilities are calculated on
// sites (links, actually).  Please keep these straight!

#ifndef DATAPACK_H
#define DATAPACK_H

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

#include "constants.h"
#include "partition.h"
#include "types.h"
#include "vectorx.h"

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

class Region;

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

class DataPack
{
  private:
    DataPack(const DataPack&);          // undefined
    DataPack& operator=(const DataPack&); // undefined

    vector<Region *> m_regions;

    PartitionNames m_partnames;
    StringVec1d m_outputpopnames;       // In the single population case save the MIG/DIVMIG partition names here.
    LongVec1d m_finalcount;             // This is set by SetFinalPartitionCount.

  public:

    DataPack() {};
    ~DataPack();

    long GetNTips() const;              // Return the total number of tips in all regions.

    long AddPartition(force_type, const string& partname);

    long GetNPartitionsByForceType(force_type) const;
    string GetPartitionName(force_type, long index) const;
    long GetPartitionNumber(force_type, const string& name) const;
    StringVec1d GetAllPartitionNames(force_type) const;
    StringVec1d GetAllCrossPartitionNames() const;

    // This function is provided to interface with tipdata objects it's also used by GetAllCrossPartitionNames
    // which needs to pass false as an argument (it cares about partition forces with only one partition.
    std::vector<std::map<force_type,std::string> >
    GetCrossPartitionIds(bool ignoresinglepop = true) const;

    // This function will return 0 if the membership vector is empty.
    // It does this to interface with the BranchBuffer and Branch::ScoreEvent.
    long GetCrossPartitionIndex(const LongVec1d& membership) const;
    LongVec1d GetBranchMembership(long xpartindex) const;
    std::map<force_type,string> GetTipId(long xpartindex) const;

    long GetNPartitionForces() const;
    long GetNCrossPartitions() const;
    long GetNPartitions(unsigned long index) const;
    LongVec1d GetAllNPartitions() const;
    long GetNumTipPopulations() const;

    void SetFinalPartitionCounts(LongVec1d pcounts); // Called by ForceSummary::SummarizeData

    void SetRegion(Region* r);

    long        GetNMaxLoci()             const;
    long        GetNRegions()             const {return m_regions.size();};
    vector<Region*>& GetAllRegions()            {return m_regions;};
    const vector<Region*>& GetAllRegions() const {return m_regions;};

    Region&     GetRegion(long n)               {assert(n < static_cast<long>(m_regions.size()));
        return *m_regions[n];};
    const Region&     GetRegion(long n)   const {assert(n < static_cast<long>(m_regions.size()));
        return *m_regions[n];};

    long GetNumMovingLoci(long reg) const;
    StringVec1d GetAllRegionNames() const;
    StringVec2d GetAllLociNames() const; // dim: region X locus
    StringVec2d GetAllLociDataTypes() const; // dim: region X locus
    StringVec2d GetAllLociMuRates() const; // dim: region X locus

    StringVec1d ToXML(unsigned long nspaces) const; // used by XMLOutfile::Display()

    // The next function is a helper function for the Menu subclass dealing with rearrangement.
    bool        CanHapArrange()           const;

    // True if you have at least two linked markers.
    bool        CanMeasureRecombination()   const;

    // This function is for the reportpage.
    bool        AnyMapping()              const;

    // Helper function for the XML-parser.
    void        RemoveUneededPartitions();

    // Helper function for the F84 data model.
    DoubleVec1d CountOverallBaseFreqs() const;

    // Helper function for lamarc FinishRegistry().
    DoubleVec2d CreateParamScalarVector() const;

    // Helper function for reportpage filling.
    DoubleVec1d GetRegionalPopSizeScalars() const;
    LongVec1d   GetNumAllLociPerRegion() const;
    bool HasMultiLocus() const;

    // Helper functions for XML parsing.
    bool IsDuplicateRegionName(const string& newname) const;
    Region* GetRegionByName(const string& name);

    // The following two functions are used only when JSIM is defined:
    // Parallel run of fluctuate.
    void WriteFlucFile(const string& outputfilename) const;
    //
    // Doesn't handle loci or spacing.
    void WritePopulationXMLFiles(bool separate_regions) const;
};

#endif // DATAPACK_H

//____________________________________________________________________________________
