// $Id: chainstate.h,v 1.14 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 */


// ChainState encapsulates the parts of Chain's internal state that
// need to be used by Arranger, Event, CollectionManager and Collector.
// It is owned and managed by Chain.
// This is a "leaf" class, and is not meant to be derived from.

#ifndef CHAINSTATE_H
#define CHAINSTATE_H

#include <cassert>
#include "vectorx.h"
#include "forceparam.h"

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

class Tree;

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

class ChainState
{
  private:
    Tree* m_tree;               // non-owning pointer to regional tree
    // (but every chainstate points to a distinct tree!)
    Tree* m_oldtree;            // owning pointer to a copy of regional tree
    ForceParameters m_parameters;
    ForceParameters m_oldparameters;

    bool unsampled_tree;        // tree has changed since last sampling
    bool unsampled_parameters;  // parameters have changed since last sampling
    bool unsampled_stick;       // stick has changed since last sampling
    bool unsampled_map;         // map position or tree changed since last sampling

    bool unexported_parameters; // parameters have changed since last
    // arranger update

  public:
    ChainState();
    ~ChainState();
    ChainState(const ChainState& src);
    ChainState& operator=(const ChainState& src);

    // Setters
    void SetTree(Tree* tree);   // sets m_tree and makes m_oldtree a partial copy of it
    void SetParameters(const ForceParameters& params);
    void OverwriteTree();       // makes m_tree a full copy of m_oldtree
    void OverwriteOldTree();    // makes m_oldtree a full copy of m_tree
    void OverwriteParameters();
    void OverwriteOldParameters();
    void SetOldTree(Tree* tree);
    void UpdateOldStickParams();
    void UpdateNewStickParams();

    void SimulateDataIfNeeded();

    // The following are called to record modification to an object
    // The first three are used by Arranger, the last by Chain
    void TreeChanged();
    void ParametersChanged();
    void StickChanged();
    void MapChanged();
    void AllChanged();   // used at start of a new chain

    // The following are called to record sampling of an object
    void TreeSampled()          { unsampled_tree = false; };
    void ParametersSampled()    { unsampled_parameters = false; };
    void StickSampled()         { unsampled_stick = false; };
    void MapSampled()           { unsampled_map = false; };
    void ParametersExported()   { unexported_parameters = false; };

    // Getters; used by Chain and Arrangers
    Tree*       GetTree()                  { assert(m_tree); return m_tree; };
    Tree*       GetOldTree()               { assert(m_oldtree); return m_oldtree; };
    ForceParameters& GetParameters()       { return m_parameters; };
    ForceParameters& GetOldParameters()    { return m_oldparameters; };

    // The following test if an object has been modified since it was last sampled
    // Used by Collectors
    bool TreeNeedsSampling()      const      { return unsampled_tree; };
    bool ParametersNeedSampling() const      { return unsampled_parameters; };
    bool StickNeedsSampling()     const      { return unsampled_stick; };
    bool MapNeedsSampling()       const      { return unsampled_map; };
    bool ParametersNeedExport()   const      { return unexported_parameters; };

    // Swapping routine for heated Bayesian runs
    void SwapParameters(ChainState& other);
};

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

#endif  // CHAINSTATE_H

//____________________________________________________________________________________
