// $Id: branchbuffer.h,v 1.18 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 a time ordered container of Branch_ptr, BranchBuffer.  The BranchBuffer
// is a storage buffer used during rearrangement to store active and inactive branches.

#ifndef BRANCHBUFFER_H
#define BRANCHBUFFER_H

#include <map>
#include <vector>

#include "branch.h"
#include "defaults.h"
#include "definitions.h"
#include "range.h"                      // For Link-related typedefs and constants.
#include "types.h"
#include "vectorx.h"

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

// #include "branch.h"--to create the "base" branch, TimeList constructor
//                      to create a Tbranch, CreateTip
//                      to initialize branch innards, both of the above
//                      to maintain tree child and parent relationships
//                         in CopyBody()
//                      to maintain tree child and parent relationships
//                         in CopyPartialBody()
//                      to track ncuttable via branch.Cuttable()
//                      to track marked status via branch.marked,
//                         branch.SetUpdateDL()

class TipData;
class DataPack;
class FC_Status;

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

class BranchBuffer
{
  private:
    Branchlist m_branches;              // We do not own these branches!
    LongVec1d m_branchxparts;           // dim: cross partitions
    LongVec2d m_branchparts;            // dim: partition force X partitions

    BranchBuffer(const BranchBuffer & src);             // undefined
    BranchBuffer & operator=(const BranchBuffer & src); // undefined
    BranchBuffer();                                     // undefined

    long GetNBranches(force_type force, const LongVec1d & membership) const;
    long GetNPartBranches(force_type force, long part) const;

  public:
    BranchBuffer(const DataPack& dpack);
    ~BranchBuffer() {};
    void Clear();
    LongVec2d GetBranchParts()                    const { return m_branchparts; };
    LongVec1d GetBranchParts(force_type force)    const;
    LongVec1d GetBranchXParts()                   const;
    void Append(Branch_ptr newbranch);
    void Append(std::vector<Branch_ptr> newbranches);
    void AddAfter(Branchiter here, Branch_ptr newbranch);
    void Collate(Branch_ptr newbranch);
    long Size()                          const { return m_branches.size(); };
    Branchiter BeginBranch()                   { return m_branches.begin(); };
    Branchiter EndBranch()                     { return m_branches.end(); };
    Branchconstiter BeginBranch() const        { return m_branches.begin(); };
    Branchconstiter EndBranch() const          { return m_branches.end(); };
    void       Remove(Branchiter here);
    void       Remove(Branch_ptr branch);
    Branch_ptr GetFirst();
    Branch_ptr RemoveFirst();
    Branch_ptr RemoveBranch(force_type force, long xpartindex, double rnd);
    Branch_ptr RemoveBranch(force_type force, const LongVec1d & membership, double rnd);
    Branch_ptr RemovePartitionBranch(force_type force, long part, double rnd);

    // This routine updates the "current branch count" storage in the BranchBuffer to make
    // its count of partitions and crosspartitions accurate for a new time slice.  Passing
    // true means that the partitions being passed are newly added; passing false means that they
    // are newly removed.  For example, if you were moving down past a coalescence, you would want
    // to remove the two lineages that were coalescing, and add the lineage they coalesce into.

    void UpdateBranchCounts(const LongVec1d & newpartitions, bool addbranch = true);

    // Meant to only be used on arranger::inactivelist().
    double  IntervalBottom();
    double  NextIntervalBottom();

    // Used by TreeSizeArranger.
    vector<Branch_ptr> ExtractConstBranches() const;

    // Used by ResimArranger::Resimulate & DropAll to aid in constructing a fc_status object.
    long   Nsites() const;

    // Used by ResimArranger::Resimulate & DropAll to setup the fc object's site counts.
    void   IncreaseFCCount(FC_Status & fcstatus) const;

    // Debugging functions.
    void PrintEvents() const;
    void PrintRanges() const;
    void PrintXParts() const;
    Linkweight AccumulatedCurTargetLinkweight() const;
    Linkweight AccumulatedNewTargetLinkweight() const;
};

#endif // BRANCHBUFFER_H

//____________________________________________________________________________________
