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


// The ChainManager is one of the big persistent objects in Lamarc.  It
// is expected to exist from the end of the intial factory phase til
// after the last output report is displayed to the user.
//
// The ChainManager is primarily responsible for providing runtime user
// output (through a RunReport), for managing the interface between the
// posterior likelihood calculator/maximizer and the running chains,
// and for providing end of program user output (through an
// OutputFile).  It is also responsible for taking the user's input
// on chain length and refactoring it for use by its stable of Chains.
//
// It owns the 2 big collections of chain output: the ChainPack, which
// goes to user output; and a collection manager that is
// utilized by the posterior likelihood calculator.

#ifndef CHAINMAN_H
#define CHAINMAN_H

#include <vector>
#include <fstream>

#include "chainpack.h"
#include "collector.h"
#include "collmanager.h"
#include "constants.h"
#include "sumfilehandler.h"
#include "vectorx.h"

// this dumps the final coalescence times of each tree
// to the file rdata
// JRM Debug 4/10
//#define DUMP_TREE_COAL_RDATA

#ifdef DUMP_TREE_COAL_RDATA
// file for data for R to process
extern std::ofstream rdata; // JRM debug
#endif

class BayesAnalyzer_1D;
class Random;
class RunReport;
class ChainParameters;
class Chain;
class Maximizer;

class ChainManager
{
  public:
    ChainManager(RunReport& runrep, Maximizer& maximize);
    ~ChainManager();
    void DoAllChains();
    const ChainPack & GetChainPack() const;


  private:
    ChainManager();                                   // undefined
    ChainManager(const ChainManager& src);            // undefined
    ChainManager& operator=(const ChainManager& src); // undefined

    const ChainParameters& m_chainparam;
    RunReport& m_runreport;
    Random& m_randomsource;
    Maximizer& m_maximizer;
    BayesAnalyzer_1D& m_bayesanalyzer;
    ChainPack m_chainpack;
    long int m_nregions, m_nreplicates;
    CollectionManager m_collectionmanager;
    SumFileHandler m_sumfilehandler;

    bool m_multitemp;
    LongVec1d m_nsteps;            // dim: chaintype
    LongVec2d m_chunksize;         // dim: chaintype X chunk
    std::vector<Chain> m_temps;         // dim: temperatures
    long int m_totalsteps, m_currentsteps; // used for completion-time prognosis

    DoubleVec2d m_logGeyerWeights;

    bool m_writesumfile;
    bool m_readsumfile;
    // true if in the process of reading or writing tree summaries to a file.

    bool m_recoversumfile;  //true if picking up in the middle
    long int m_recover_region;
    long int m_recover_replicate;
    long int m_recover_chaintype;
    long int m_recover_chain;   // All recover_* variables are indices, not counters.
    bool m_recover_redochain;
    bool m_recover_redomaximization;
    bool m_redoreplicatesum;
    bool m_redoregionsum;

    vector<Tree*> m_regiontrees;  // the trees for the various temperature chains

    void ReadInRecover();
    void SetRecoverChaintypeChainsFrom(long int last_chain);
    void TellUserWhereWeAreRestarting();
    void CreateChains();
    void DoRegions();
    void CalculateMLEsOverRegions();
    void CalculateNonBayesMultiRegionMLEs(ForceParameters & fp, ChainOut & regionout, double & maxlike);
    void DoReplicates(long int region);
    void DoChainTypes(long int region, long int rep);
    // the following handles maximization on a stored-tree chain
    void DoChainFromSummaryFile(long int region, long int rep, long int chaintype, long int chain);
    void DoChain(long int region, long int rep, long int chaintype, long int chain, ForceParameters& chainstart);
    void GroomTrees(ForceParameters& chainstart);
    unsigned long int FindColdChain(const vector<Chain> & chains) const;
    void DoSingleChainPosterior(long int region, long int rep, long int chaintype,
                                long int chain, ChainOut & chout, ForceParameters & chainstart);
    void DoSingleChainBayes(long int region, long int rep, ChainOut & chout, ForceParameters & chainstart);

    // Adjust temperatures for adaptive heating
    void AdjustTemperatures(DoubleVec1d & averagetemps, long int step, double & howoften);
    void ChooseTwoAdjacentChains(unsigned long int & chain1, unsigned long int & chain2);
    std::vector<std::pair<double, long int> > SortChainsByTemperature(const vector<Chain> & temps);

    void ReadInNoRedoMax(long int region);
    void RedoMaximization(long int region);
    void CompareAndWarn(ForceParameters calcfp, ForceParameters readfp);
    void DoOverallProfiles();
    void CloseSumOut();
    void SaveGeyerWeights(DoubleVec1d logGeyerWeights, long int region);
    void OptimizeDataModels(long int reg);
    void ResetAllAlphas();
};

#endif // CHAINMAN_H

//____________________________________________________________________________________
