// $Id: reportpage.h,v 1.40 2018/01/03 21:33:02 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 base class ReportPage represents a single page of the output
 report; subclasses produce specific pages.

 Written by Jon Yamato
*******************************************************************/

#ifndef REPORTPAGE_H
#define REPORTPAGE_H

#include <map>
#include <string>
#include <vector>

#include "types.h"

using std::map;
using std::ofstream;
using std::string;
struct PlotStruct;
class Parameter;
class RegionGammaInfo;

const long DEFLENGTH = 60;
const char DEFDLM='=';

typedef std::map<string, string> Strmap;
typedef std::map<string, string>::iterator Strmapiter;
typedef std::vector< std::pair < string, string> > StrPairVec;
typedef std::vector< std::pair < string, string> >::iterator StrPairVecIter;

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

class ReportPage
{

  private:
    ReportPage();  // deliberately undefined

  protected:
    ofstream &outf;
    vector<string> pagetitle;
    char titledlm;
    unsigned long pagelength, pagewidth, current_length;
    verbosity_type verbosity;
    bool m_bayesanalysis;
    string m_MLE;

    string MakeLineOf(const char ch, long length=DEFLINELENGTH,
                      long indent=DEFINDENT);
    string MakePageBreak();
    string MakeBlankLine();
    vector<string> MakeTitle();
    virtual vector<string> MakeTableTitle(const string &title);
    virtual vector<string> MakeTableTitle(const char *title);
    StringVec1d GetOneRow(const StringVec2d table, const long rownum);
    virtual string MakeSimpleRow(vector<long>& colwdth, vector<string>& contents);
    virtual string MakeTwoCol(const vector<long>& colwdth, const string& col1,
                              const string& col2);
    virtual string MakeTwoCol(const vector<long>& colwdth, const string& col1,
                              const char* col2);
    virtual string MakeTwoCol(const vector<long>& colwdth, const char* col1,
                              const string& col2);
    virtual string MakeTwoCol(const vector<long>& colwdth, const char* col1,
                              const char* col2);

    virtual string MakeSectionBreak(const char dlm=DEFDLM,
                                    long width=DEFLINELENGTH, long indent=DEFINDENT);
    virtual vector<string> MakeTable(vector<string> &colhdr, StringVec2d &rowhdr,
                                     vector<long>& colwdth, StringVec3d &innards);

    void PrintTitle();
    void PrintLineOf(const char ch, long length=DEFLINELENGTH,
                     long indent=DEFINDENT);
    void PrintPageBreak();
    void PrintBlankLine();

    virtual void PrintSimpleRow(vector<long> &colwdth, vector<string> &contents);
    virtual void PrintTwoCol(const vector<long> &colwdth, const string &col1,
                             const string &col2);
    virtual void PrintTwoCol(const vector<long> &colwdth, const char *col1,
                             const string &col2);
    virtual void PrintTwoCol(const vector<long> &colwdth, const string &col1,
                             const char *col2);
    virtual void PrintTwoCol(const vector<long> &colwdth, const char *col1,
                             const char *col2);
    virtual void PrintCenteredString(const string &str, long width=DEFLINELENGTH,
                                     long indent=DEFINDENT, bool trunc = true);
    virtual void PrintWrapped(const string &line);
    virtual void PrintWrapped(const StringVec1d& line);
    virtual void PrintCenteredString(const char *str, long width=DEFLINELENGTH,
                                     long indent=DEFINDENT, bool trunc = true);
    virtual void PrintTableTitle(const string &title);
    virtual void PrintTableTitle(const char *title);
    virtual void PrintSectionBreak(const char dlm=DEFDLM,
                                   long width=DEFLINELENGTH, long indent=DEFINDENT);
    virtual void PrintTable(vector<string> &colhdr, StringVec2d &rowhdr,
                            vector<long> &colwdth,  StringVec3d &innards);

    // helper functions for the MlePage and ProfPage
    StringVec2d SortTable(StringVec2d intable, unsigned long sortcol,
                          unsigned long headerrows);
    bool MakeItShorter(string& title, const unsigned long width);

  public:
    ReportPage(ofstream& pf, long pglngth=DEFLENGTH, long pgwdth=DEFLINELENGTH);
    //  We accept the default for these and other ReportPage objects.
    //ReportPage(const ReportPage &src);
    //virtual ReportPage &operator=(const ReportPage &src);
    virtual ~ReportPage() {};

    static  double GetCentile(const vector<centilepair>& centiles,
                              double pcent);
    static  double GetReverseCentile(const vector<centilepair>& centiles,
                                     double pcent);
    virtual void Setup(vector<string> &title, long pglength=DEFLENGTH,
                       long pgwidth=DEFLINELENGTH, char tdlm=DEFDLM);
    virtual void Setup(string &title, long pglength=DEFLENGTH,
                       long pgwidth=DEFLINELENGTH, char tdlm=DEFDLM);
    virtual void Setup(const char *title, long pglength=DEFLENGTH,
                       long pgwidth=DEFLINELENGTH, char tdlm=DEFDLM);
    virtual void Show() = 0;

    static void TrimString(string& title);
};

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

class MlePage : public ReportPage
{
  protected:
    const long hdrindent;
    long npops;
    unsigned long colwidth;
    long label_colwidth;
    StringVec3d allforcetable;

    //  virtual void CopyMembers(const MlePage &src);
    void WritePriors();
    void WriteBody();
    StringVec1d DoPercentiles(long region,
                              vector<Parameter>::const_iterator param,
                              const DoubleVec1d& modifiers,
                              Strmap& namemap);
    StringVec1d MakeLabels(const StringVec1d subtypes, const DoubleVec1d modifiers, const bool usepercentile);
    StringVec1d MakeColumn(const string& forcename, const string& paramname,
                           const string& regionname, const double MLE,
                           const StringVec1d& percentiles, const bool usepercentiles);
    void DoRegionGammaInfo(StringVec3d& allforcetable, Strmap& namemap,
                           const RegionGammaInfo *pRegionGammaInfo);
    void AddForceToOutput(StringVec3d& allforcetable, StringVec2d forcetable);
    bool DoColumnsMatch(const StringVec1d col1, const StringVec1d col2);
    void WrapOutput(StringVec3d& allforcetable);
    void WriteOutput(StringVec3d& allforcetable, Strmap namemap);
    void NixRedundancy(StringVec1d& row, StrPairVec& legend, Strmap namemap,
                       vector<bool>& breaks);
    void WriteLine(const StringVec1d line);

    // simulation specific code--to print something easily machine parsible
    void WriteSimMles();

  public:
    MlePage(ofstream& pf, long pglngth=DEFLENGTH, long pgwdth=DEFLINELENGTH);
    MlePage(const MlePage &src); //Undefined
    virtual ~MlePage() {};
    virtual void Show();

};

class MapPage : public ReportPage
{
  public:
    MapPage(ofstream& pf, long pglngth=DEFLENGTH, long pgwdth=DEFLINELENGTH);
    virtual ~MapPage() {};

    virtual void Show();
};

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

class ProfPage : public ReportPage
{
  protected:
    unsigned long colwidth;

    //  virtual void CopyAllMembers(const ProfPage& src);
    virtual void DisplayParameters(const ParamVector& params, long region);
    StringVec1d MakeColumn(const string& name, const string& mle,
                           const StringVec1d mod_strings, const bool mixedmult);
    StringVec1d MakeGrowFixedColumn();
    StringVec1d MakeLogisticSelectionFixedColumn();
    DoubleVec1d MakeLogisticSelectionFixedModifiers(double mle);
    StringVec1d MakeModColFrom(const vector<centilepair>& numbers,
                               const DoubleVec1d modifiers,
                               vector<bool> badLnLs,
                               bool bayesfixed = false);
    StringVec1d MakeLnLColFrom(const vector<centilepair>& numbers,
                               const DoubleVec1d modifiers,
                               vector<bool>& badLnLs);
    StringVec3d WrapTable(StringVec2d& forcetable);
    virtual void PrintTable(StringVec3d& wrappedtable);
    void PrintProfileLine(StringVec1d& line);

  public:
    ProfPage(ofstream& pf, long pglngth=DEFLENGTH, long pgwdth=DEFLINELENGTH);
    static void TradeValsForPercs(DoubleVec1d& modifiers, vector<centilepair> CIvec);
    static DoubleVec1d MakeGrowFixedModifiers(double mle);

    virtual void Show();
};

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

class UsrPage : public ReportPage
{
  protected:
    long npops;
    vector<long> m_colwidths;

    //virtual void CopyMembers(const UsrPage &src);

  public:
    UsrPage(ofstream& pf, long pglngth=DEFLENGTH, long pgwdth=DEFLINELENGTH);
    virtual ~UsrPage() {};

    virtual void Show();
};

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

class DataPage : public ReportPage
{

  private:
    const long table1, table2;
    long nxparts;
    vector<long> m_colwidths;

  protected:
    //virtual void CopyMembers(const DataPage &src);
    virtual vector<string> SetupColhdr(long whichtable);
    virtual StringVec2d SetupRowhdr(long whichtable);
    virtual StringVec3d SetupInnards(long whichtable);

  public:
    DataPage(ofstream& pf, long pglngth=DEFLENGTH, long pgwdth=DEFLINELENGTH);
    virtual ~DataPage() {};

    virtual void Show();
};

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

class RunPage : public ReportPage
{

  private:
    vector<long> m_colwidths;

  public:
    RunPage(ofstream& pf, long pglngth=DEFLENGTH, long pgwdth=DEFLINELENGTH);
    virtual ~RunPage() {};

    virtual void Show();
};

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

class LikePage : public ReportPage
{
  private:
    bool Divides(long x, long y);
    bool EmptyPlot(PlotStruct& plot);

  public:
    LikePage(ofstream& pf, long pglngth=DEFLENGTH, long pgwdth=DEFLINELENGTH);
    virtual ~LikePage() {};

    string MakeBorder(long points, long breaks = 4);
    vector<string> MakeInnards(const DoubleVec2d& likes);
    vector<string> MakeLikePlot(const StringVec1d& innards,
                                const Parameter& paramX, const Parameter& paramY, long breaks = 4);
    DoubleVec2d AddGraphs(const DoubleVec2d& a, const DoubleVec2d& b);

    virtual void Show();
};

#endif // REPORTPAGE_H

//____________________________________________________________________________________
