// $Id: summary.h,v 1.43 2018/01/03 21:33:04 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 is a Force-polymorphic class which works with the IntervalData
  class (non-polymorphic) to provide needed summary information about
  a tree.  It can provide either Short or Long forms of its summary,
  depending on the presence or absence of perturbing forces like Growth
  (if Growth is in effect Long forms are necessary).

  Written by Mary Kuhner
*/

#ifndef SUMMARY_H
#define SUMMARY_H

#include <iostream>
#include <list>
#include <string>

#include "constants.h"
#include "intervaldata.h"               // For IntervalData member.
#include "range.h"                      // For Link-related typedefs and constants.
#include "registry.h"                   // For use of GetDataPack() and GetForceSummary() to set npop & m_nparams.
#include "vectorx.h"

struct Interval;

class Summary
{
  private:
    Summary(const Summary &);             // not defined
    Summary & operator=(const Summary &); // not defined

  protected:

    IntervalData& m_intervalData;
    DoubleVec1d m_shortpoint;           // pre-computed ShortPoint results
    // dimensioned by # of parameters
    DoubleVec1d m_shortwait;            // pre-computed ShortWait results
    // dimensioned by # of parameters
    LongVec2d m_shortpicks;             // pre-computed ShortPicks results
    // dimensioned by #localpartitionforces
    // and #alleles per force
    long m_nparams;
    bool m_shortness;
    IntervalData m_fakeIntervals;

    // pointers into the linked list in m_intervalData, or possibly
    // into m_fakeIntervals instead
    Interval* m_front;                  // front interval of our type
    Interval* m_back;                   // most recently added interval of our type

    virtual void ComputeShortPoint() = 0;
    virtual void ComputeShortWait() = 0;
    virtual void ComputeShortPicks() {};

  public:

    Summary(IntervalData& interval, long npars, bool shortform)
        : m_intervalData(interval), m_nparams(npars), m_shortness(shortform),
          m_front(NULL), m_back(NULL)
    {};

    virtual ~Summary() {};

    virtual Summary * Clone(IntervalData& interval) const = 0;

    const DoubleVec1d & GetShortPoint() const; // nCoalescences, etc.
    const DoubleVec1d & GetShortWait() const;  // k(k-1)t, etc.
    // GetShortPicks must return a completely empty vector
    // if there are no localpartition+recombination forces on
    const LongVec2d & GetShortPicks() const; // forces x alleles

    Interval const * GetLongPoint() const;
    const std::list<Interval> & GetLongWait() const;
    // there is no GetLongPicks() because GetLongPoint() does its job

    void AddInterval(double time, const LongVec2d & pk, const LongVec1d & xk,
                     Linkweight recweight, xpart_t ostat, xpart_t nstat,
                     long int recpoint, const LongVec1d & picks, force_type type);

    virtual void AdjustSummary(const DoubleVec1d & totals, long region) = 0;

    bool Compress();

    virtual string GetType() const = 0;
    bool GetShortness() const;

    // Functions for reading in data from a summary file:
    void AddShortPoint(string);
    void AddShortWait(string);
    void AddShortPicks(const StringVec1d &);
    void SetShortness( bool a ) { m_shortness = a; };

    // Function added for tree summarization in presence of
    // recombination & disease
    Interval* GetLastAdded() { return m_back; };
};

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

class CoalSummary : public Summary
{
  private:

    virtual void ComputeShortPoint();  // nCoalescences, etc.
    virtual void ComputeShortWait();   // k(k-1)t, etc.
    virtual void ComputeShortPicks();  // partitions picked during recombinations

  public:

    CoalSummary(IntervalData& interval, bool shortform)
        : Summary(interval, registry.GetForceSummary().GetNParameters(force_COAL), shortform)
    {};

    virtual ~CoalSummary() {};
    virtual Summary * Clone(IntervalData& interval) const;
    virtual void AdjustSummary(const DoubleVec1d & totals, long region);
    virtual string GetType() const { return lamarcstrings::COAL; };

};

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

class MigSummary : public Summary
{
  private:

    virtual void ComputeShortPoint();
    virtual void ComputeShortWait();
    xpart_t m_npop;
    xpart_t m_migpartindex;

  public:

    MigSummary(IntervalData& interval, bool shortform)
        : Summary(interval, registry.GetForceSummary().GetNParameters(force_MIG), shortform),
          m_npop(registry.GetDataPack().GetNPartitionsByForceType(force_MIG)),
          m_migpartindex(registry.GetForceSummary().GetPartIndex(force_MIG))
    {};

    virtual ~MigSummary() {};
    virtual Summary * Clone(IntervalData& interval) const;
    virtual void AdjustSummary(const DoubleVec1d & totals, long region);
    virtual string GetType() const { return lamarcstrings::MIG; };

};

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

class DiseaseSummary : public Summary
{
  private:
    virtual void ComputeShortPoint();
    virtual void ComputeShortWait();
    xpart_t m_nstati;
    xpart_t m_dispartindex;

  public:
    DiseaseSummary(IntervalData& interval, bool shortform)
        : Summary(interval, registry.GetForceSummary().GetNParameters(force_DISEASE), shortform),
          m_nstati(registry.GetDataPack().GetNPartitionsByForceType(force_DISEASE)),
          m_dispartindex(registry.GetForceSummary().GetPartIndex(force_DISEASE))
    {};

    virtual ~DiseaseSummary() {};
    virtual Summary * Clone(IntervalData& interval) const;
    virtual void AdjustSummary(const DoubleVec1d & totals, long region);
    virtual string GetType() const { return lamarcstrings::DISEASE; };

};

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

class EpochSummary : public Summary
{
  private:
    // The following two functions do nothing, as no summary statistics can be
    // collected on occurance of Epochs (the number of Epochs is fixed).
    virtual void ComputeShortPoint() {};
    virtual void ComputeShortWait() {};
    xpart_t m_npop;
    xpart_t m_migpartindex;

  public:
    EpochSummary(IntervalData& interval, bool shortform)
        : Summary(interval, registry.GetForceSummary().GetNParameters(force_DIVERGENCE), shortform),
          m_npop(registry.GetDataPack().GetNPartitionsByForceType(force_DIVMIG)),
          m_migpartindex(registry.GetForceSummary().GetPartIndex(force_DIVMIG))
    {};

    virtual ~EpochSummary() {};
    virtual Summary * Clone(IntervalData& interval) const;
    virtual void AdjustSummary(const DoubleVec1d &, long) {};
    virtual string GetType() const { return lamarcstrings::DIVERGENCE; };

};

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

class RecSummary : public Summary
{
  private:
    virtual void ComputeShortPoint();
    virtual void ComputeShortWait();

    LongVec1d m_nrecsbyxpart;
    LongVec1d m_nrecsbydispart;
    long m_nrecs;

  public:
    RecSummary(IntervalData& interval, bool shortform);
    virtual ~RecSummary() {};
    virtual Summary * Clone(IntervalData& interval) const;
    virtual void AdjustSummary(const DoubleVec1d & totals, long region);
    virtual string GetType() const { return lamarcstrings::REC; };

    void AddToRecombinationCounts(const LongVec1d & membership);
    const LongVec1d & GetNRecsByXPart() const { return m_nrecsbyxpart; };
    const LongVec1d & GetNRecsByDiseasePart() const { return m_nrecsbydispart; };
    long GetNRecs() const { return m_nrecs; };
};

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

class DivMigSummary : public Summary
{
  private:
    virtual void ComputeShortPoint();
    virtual void ComputeShortWait();
    xpart_t m_npop;
    xpart_t m_divmigpartindex;
    const std::vector<Epoch> * m_epochs;

  public:
    DivMigSummary(IntervalData& interval, bool shortform)
        : Summary(interval, registry.GetForceSummary().GetNParameters(force_DIVMIG), shortform),
          m_npop(registry.GetDataPack().GetNPartitionsByForceType(force_DIVMIG)),
          m_divmigpartindex(registry.GetForceSummary().GetPartIndex(force_DIVMIG)),
          m_epochs(registry.GetForceSummary().GetEpochs())
    {};

    virtual ~DivMigSummary() {};
    virtual Summary * Clone(IntervalData& interval) const;
    virtual void AdjustSummary(const DoubleVec1d & totals, long region);
    virtual string GetType() const { return lamarcstrings::DIVMIG; };
};

#endif // SUMMARY_H

//____________________________________________________________________________________
