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


#ifndef SETGET_H
#define SETGET_H

#include <cassert>
#include <string>

#include "constants.h"
#include "datatype.h"
#include "errhandling.h"
#include "parameter.h"
#include "stringx.h"
#include "rangex.h"
#include "ui_constants.h"
#include "ui_id.h"
#include "paramstat.h"

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

class UIVars;

// Classes defined here are for setting and getting values
// from the "backend" code.

// very basic virtual class. The parent of all SetGetTemplate<> objects
class SetGet
{
  protected:
    const std::string & uikey;
  public:
    SetGet(const std::string & key) : uikey(key) {};
    virtual ~SetGet() {};
    // UIKey should be unique -- it is used to create and
    // access a single instance of this Getter/Setter
    // and should describe what this getter/setter gets/sets
    // Each should be defined as a constant string in the
    // uistr class
    virtual const string & UIKey()
    { return uikey;};
    // Get a string describing what will be set/gotten
    virtual string Description(UIVars&, UIId)
    { return UIKey();};
    //Get a string describing the min/max values possible.
    virtual string Min(UIVars&, UIId) { return ToString(FLAGDOUBLE);};
    virtual string Max(UIVars&, UIId) { return ToString(FLAGDOUBLE);};
    // Get a string that represents the value stored in the backend
    virtual std::string GetPrintString(UIVars& vars, UIId id) = 0;
    virtual std::string NextToggleValue(UIVars&, UIId)
    { throw implementation_error("no toggle possible");};
    // returns true if the values associated with id for this
    // menu item are internally consistent -- used to verify
    // that two or more values are mutually OK.
    virtual bool IsConsistent(UIVars&, UIId)
    {
        return true;
    };
    virtual void SetFromString(UIVars&, UIId, string)
    { throw implementation_error("no SetFromString possible");};
};

//------------------------------------------------------------------------------------
// Basic methods instructing how to get and set a single
// value.
template<class ValType>
class GetTemplate : public SetGet
{
  public:
    GetTemplate(const std::string & key): SetGet(key) {};
    virtual ~GetTemplate() {};
    // reaches into the backend code to get a single value
    virtual ValType Get(UIVars& vars, UIId id) = 0;
    // default implementation -- makes a menu-printable string
    // out of the id'th associated variable
    virtual std::string GetPrintString(UIVars& vars, UIId id)
    { return MakePrintString(vars,Get(vars,id));};
    // how these values should be printed out
    virtual std::string MakePrintString(UIVars&,ValType v)
    { return ToString(v);};
};

template<class ValType>
class SetGetTemplate : public GetTemplate<ValType>
{
  public:
    SetGetTemplate(const std::string & key): GetTemplate<ValType>(key) {};
    virtual ~SetGetTemplate() {};
    // reaches into the backend code to set a single value
    virtual void Set(UIVars& vars,UIId id,ValType value) = 0;
    // converts stringVal to ValType and uses ::Set
    virtual void SetFromString(UIVars& vars, UIId id, string stringVal)
    { Set(vars,id,GetValFromString(vars,stringVal));};
    // GetValFromString converts a string to ValType
    virtual ValType GetValFromString(UIVars&,string) = 0;

};

//------------------------------------------------------------------------------------
// Refinement of GetTemplate<bool> defines only how to get
// a bool value from string input. All classes getting
// a bool value should inherit from this one.
class GetBool : public GetTemplate<bool>
{
  public:
    GetBool(const std::string & key)
        : GetTemplate<bool>(key) {};
    virtual ~GetBool() {};
};

//------------------------------------------------------------------------------------
// Refinement of GetTemplate<data_type>
class GetDataType : public GetTemplate<data_type>
{
  public:
    GetDataType(const std::string & key)
        : GetTemplate<data_type>(key) {};
    virtual ~GetDataType() {};
};

//------------------------------------------------------------------------------------
// Refinement of GetTemplate<DoubleVec1d> defines only how to get
// a DoubleVec1d value from string input. All classes getting
// a DoubleVec1d value should inherit from this one.
class GetDoubleVec1d : public GetTemplate<DoubleVec1d>
{
  public:
    GetDoubleVec1d(const std::string & key)
        : GetTemplate<DoubleVec1d>(key) {};
    virtual ~GetDoubleVec1d() {};
};

//------------------------------------------------------------------------------------
// Refinement of GetTemplate<ForceTypeVec1d> defines only how to get
// a ForceTypeVec1d value from string input. All classes getting
// a ForceTypeVec1d value should inherit from this one.
class GetForceTypeVec1d : public GetTemplate<ForceTypeVec1d>
{
  public:
    GetForceTypeVec1d(const std::string & key)
        : GetTemplate<ForceTypeVec1d>(key) {};
    virtual ~GetForceTypeVec1d() {};
};

//------------------------------------------------------------------------------------
// Refinement of GetTemplate<long int> defines only how to get
// a long int value from string input. All classes getting
// a long int value should inherit from this one.
class GetLong : public GetTemplate<long int>
{
  public:
    GetLong(const std::string & key)
        : GetTemplate<long int>(key) {};
    virtual ~GetLong() {};
};

//------------------------------------------------------------------------------------
// Refinement of GetTemplate<LongVec1d> defines only how to get
// a LongVec1d value from string input. All classes getting
// a LongVec1d value should inherit from this one.
class GetLongVec1d : public GetTemplate<LongVec1d>
{
  public:
    GetLongVec1d(const std::string & key)
        : GetTemplate<LongVec1d>(key) {};
    virtual ~GetLongVec1d() {};
};

//------------------------------------------------------------------------------------
// Refinement of GetTemplate<MethodTypeVec1d> defines only how to get
// a MethodTypeVec1d value from string input. All classes getting
// a MethodTypeVec1d value should inherit from this one.
class GetMethodTypeVec1d : public GetTemplate<MethodTypeVec1d>
{
  public:
    GetMethodTypeVec1d(const std::string & key)
        : GetTemplate<MethodTypeVec1d>(key) {};
    virtual ~GetMethodTypeVec1d() {};
};

//------------------------------------------------------------------------------------
// Refinement of GetTemplate<paramlistcondition> defines only how to get
// a paramlistcondition value from string input. All classes getting
// a paramlistcondition value should inherit from this one.
class GetParamlistcondition : public GetTemplate<paramlistcondition>
{
  public:
    GetParamlistcondition(const std::string & key)
        : GetTemplate<paramlistcondition>(key) {};
    virtual ~GetParamlistcondition() {};
};

//------------------------------------------------------------------------------------
// Refinement of GetTemplate<std::string> defines only how to get
// a std::string value from string input. All classes getting
// a std::string value should inherit from this one.
class GetString : public GetTemplate<std::string>
{
  public:
    GetString(const std::string & key)
        : GetTemplate<std::string>(key) {};
    virtual ~GetString() {};
};

//------------------------------------------------------------------------------------
// Refinement of GetTemplate<StringVec1d> defines only how to get
// a StringVec1d value from string input. All classes getting
// a StringVec1d value should inherit from this one.
class GetStringVec1d : public GetTemplate<StringVec1d>
{
  public:
    GetStringVec1d(const std::string & key)
        : GetTemplate<StringVec1d>(key) {};
    virtual ~GetStringVec1d() {};
};

//------------------------------------------------------------------------------------
// Refinement of GetTemplate<UIIdVec1d> defines only how to get
// a UIIdVec1d value from string input. All classes getting
// a UIIdVec1d value should inherit from this one.
class GetUIIdVec1d : public GetTemplate<UIIdVec1d>
{
  public:
    GetUIIdVec1d(const std::string & key)
        : GetTemplate<UIIdVec1d>(key) {};
    virtual ~GetUIIdVec1d() {};
};

//------------------------------------------------------------------------------------
// Refinement of GetTemplate<UIIdVec2d> defines only how to get
// a UIIdVec2d value from string input. All classes getting
// a UIIdVec2d value should inherit from this one.
class GetUIIdVec2d : public GetTemplate<UIIdVec2d>
{
  public:
    GetUIIdVec2d(const std::string & key)
        : GetTemplate<UIIdVec2d>(key) {};
    virtual ~GetUIIdVec2d() {};
};

//------------------------------------------------------------------------------------
// Refinement of SetGetTemplate<bool> defines only how to get
// a bool value from string input. All classes setting/getting
// a bool value should inherit from this one.
class SetGetBool : public SetGetTemplate<bool>
{
  public:
    SetGetBool(const std::string & key): SetGetTemplate<bool>(key) {};
    virtual ~SetGetBool() {};
    virtual bool GetValFromString(UIVars&,string input)
    { return ProduceBoolOrBarf(input);};
    virtual std::string NextToggleValue(UIVars& vars,UIId id)
    { bool v = Get(vars,id); return ToString(!v);};
};

//------------------------------------------------------------------------------------
// Refinement of SetGetTemplate<double> defines only how to get
// a double value from string input. All classes setting/getting
// a double value should inherit from this one.
class SetGetDouble : public SetGetTemplate<double>
{
  public:
    SetGetDouble(const std::string & key): SetGetTemplate<double>(key) {};
    virtual ~SetGetDouble() {};
    virtual double GetValFromString(UIVars&,string input)
    { return ProduceDoubleOrBarf(input);};
};

//------------------------------------------------------------------------------------
// Refinement of SetGetTemplate<growth_scheme> defines only how to get
// a growth_scheme value from string input. All classes setting/getting
// a growth_scheme value should inherit from this one.
class SetGetGrowthScheme : public SetGetTemplate<growth_scheme>
{
  public:
    SetGetGrowthScheme(const std::string & key): SetGetTemplate<growth_scheme>(key) {};
    virtual ~SetGetGrowthScheme() {};
    virtual growth_scheme GetValFromString(UIVars&,string input)
    { return ProduceGrowthSchemeOrBarf(input);};
};

//------------------------------------------------------------------------------------
// Refinement of SetGetTemplate<growth_type> defines only how to get
// a growth_type value from string input. All classes setting/getting
// a growth_type value should inherit from this one.
class SetGetGrowthType : public SetGetTemplate<growth_type>
{
  public:
    SetGetGrowthType(const std::string & key): SetGetTemplate<growth_type>(key) {};
    virtual ~SetGetGrowthType() {};
    virtual growth_type GetValFromString(UIVars&,string input)
    { return ProduceGrowthTypeOrBarf(input);};
};

//-------------------------------------------------------------------------------------
// Refinement of SetGetTemplate<selection_type> defines only how to get
// a selection_type value from string input. All classes setting/getting
// a selection_type value should inherit from this one.
class SetGetSelectionType : public SetGetTemplate<selection_type>
{
  public:
    SetGetSelectionType(const std::string & key): SetGetTemplate<selection_type>(key) {};
    virtual ~SetGetSelectionType() {};
    virtual selection_type GetValFromString(UIVars&,string input)
    { return ProduceSelectionTypeOrBarf(input);};
};

//------------------------------------------------------------------------------------
// Refinement of SetGetTemplate<long int> defines only how to get
// a long int value from string input. All classes setting/getting
// a long int value should inherit from this one.
class SetGetLong : public SetGetTemplate<long int>
{
  public:
    SetGetLong(const std::string & key): SetGetTemplate<long int>(key) {};
    virtual ~SetGetLong() {};
    virtual long int GetValFromString(UIVars&,string input)
    { return ProduceLongOrBarf(input);};
};

//------------------------------------------------------------------------------------
// Refinement of SetGetTemplate<method_type> defines only how to get
// a method_type value from string input. All classes setting/getting
// a method_type value should inherit from this one.
class SetGetMethodType : public SetGetTemplate<method_type>
{
  public:
    SetGetMethodType(const std::string & key): SetGetTemplate<method_type>(key) {};
    virtual ~SetGetMethodType() {};
    virtual method_type GetValFromString(UIVars&,string input)
    { return ProduceMethodTypeOrBarf(input);};
};

//------------------------------------------------------------------------------------
// Refinement of SetGetTemplate<string> defines only how to get
// a string value from string input. All classes setting/getting
// a string value should inherit from this one.
class SetGetString : public SetGetTemplate<std::string>
{
  public:
    SetGetString(const std::string & key): SetGetTemplate<std::string>(key) {};
    virtual ~SetGetString() {};
    virtual string GetValFromString(UIVars&,string input)
    { return input;};
};

//------------------------------------------------------------------------------------
// Refinement of SetGetTemplate<model_type> defines only how to get
// a string value from model_type input. All classes setting/getting
// a model_type value should inherit from this one.
class SetGetModelType : public SetGetTemplate<model_type>
{
  public:
    SetGetModelType(const std::string & key): SetGetTemplate<model_type>(key) {};
    virtual ~SetGetModelType() {};
    virtual model_type GetValFromString(UIVars&,string input)
    { return ProduceModelTypeOrBarf(input);};
};

//------------------------------------------------------------------------------------
// Refinement of SetGetTemplate<proftype> defines only how to get
// a string value from proftype input. All classes setting/getting
// a proftype value should inherit from this one.
class SetGetProftype : public SetGetTemplate<proftype>
{
  public:
    SetGetProftype(const std::string & key): SetGetTemplate<proftype>(key) {};
    virtual ~SetGetProftype() {};
    virtual proftype GetValFromString(UIVars&,string input)
    { return ProduceProftypeOrBarf(input);};
    virtual std::string NextToggleValue(UIVars& vars,UIId id)
    {
        switch(Get(vars,id))
        {
            case profile_NONE:
                return ToString(profile_FIX);
                break;
            case profile_FIX:
                return ToString(profile_PERCENTILE);
                break;
            case profile_PERCENTILE:
                return ToString(profile_NONE);
                break;
        }
        return "UNKNOWN";  // should not happen; this line was
        // added to silence compiler warning
    };
};

class SetGetIndividualParamstatus : public SetGetTemplate<ParamStatus>
{
  public:
    SetGetIndividualParamstatus(const std::string & key): SetGetTemplate<ParamStatus>(key) {};
    virtual ~SetGetIndividualParamstatus() {};
    virtual ParamStatus GetValFromString(UIVars&,string input)
    { return ProduceParamstatusOrBarf(input);};
    virtual std::string NextToggleValue(UIVars& vars,UIId id)
    {
        return (Get(vars,id).ToggleIndividualStatus(id.GetForceType()));
    };
};

class SetGetGroupParamstatus : public SetGetTemplate<ParamStatus>
{
  public:
    SetGetGroupParamstatus(const std::string & key): SetGetTemplate<ParamStatus>(key) {};
    virtual ~SetGetGroupParamstatus() {};
    virtual ParamStatus GetValFromString(UIVars&,string input)
    { return ProduceParamstatusOrBarf(input);};
    virtual std::string NextToggleValue(UIVars& vars,UIId id)
    {
        return (Get(vars,id).ToggleGroupStatus(id.GetForceType()));
    };
};

//------------------------------------------------------------------------------------
// Refinement of SetGetTemplate<verbosity_type> defines only how to get
// a string value from verbosity_type input. All classes setting/getting
// a verbosity_type value should inherit from this one.
class SetGetVerbosityType : public SetGetTemplate<verbosity_type>
{
  public:
    SetGetVerbosityType(const std::string & key)
        : SetGetTemplate<verbosity_type>(key) {};
    virtual ~SetGetVerbosityType() {};
    virtual verbosity_type GetValFromString(UIVars&,string input)
    { return ProduceVerbosityTypeOrBarf(input);};
    virtual std::string NextToggleValue(UIVars& vars, UIId id)
    {
        switch(Get(vars,id))
        {
            case NONE:
                return ToString(CONCISE);
                break;
            case CONCISE:
                return ToString(NORMAL);
                break;
            case NORMAL:
                return ToString(VERBOSE);
                break;
            case VERBOSE:
                return ToString(NONE);
                break;
        }
        return "UNKNOWN";  // line should never be reached;
        // it's here to silence compiler warnings
    };
};

//Since we want to exclude 'none' as an option for output file verbosity,
// this class sets NextToggleValue to skip over it (but can handle the case
// where it receives it as input, if, say, it was read in from the input file).

class SetGetVerbosityTypeNoNone : public SetGetTemplate<verbosity_type>
{
  public:
    SetGetVerbosityTypeNoNone(const std::string & key)
        : SetGetTemplate<verbosity_type>(key) {};
    virtual ~SetGetVerbosityTypeNoNone() {};
    virtual verbosity_type GetValFromString(UIVars&, string input)
    { return ProduceVerbosityTypeOrBarf(input);};
    virtual std::string NextToggleValue(UIVars& vars, UIId id)
    {
        switch(Get(vars,id))
        {
            case NONE:
                return ToString(CONCISE);
                break;
            case CONCISE:
                return ToString(NORMAL);
                break;
            case NORMAL:
                return ToString(VERBOSE);
                break;
            case VERBOSE:
                return ToString(CONCISE);
                break;
        }
        return "UNKNOWN";  // line should never be reached;
        // it's here to silence compiler warnings
    };
};

//For now, there are only two possible prior types, but there may be more in
// the future.  If that changes, the bounds may need more information, too.
class SetGetPriorType : public SetGetTemplate<priortype>
{
  public:
    SetGetPriorType(const std::string & key)
        : SetGetTemplate<priortype>(key) {};
    virtual ~SetGetPriorType() {};
    virtual priortype GetValFromString(UIVars&, string input)
    { return ProducePriorTypeOrBarf(input);};
    virtual std::string NextToggleValue(UIVars& vars, UIId id)
    {
        switch(Get(vars,id))
        {
            case LINEAR:
                if (id.GetForceType()==force_GROW) {
                    return ToString(LINEAR);
                }
                return ToString(LOGARITHMIC);
                break;
            case LOGARITHMIC:
                return ToString(LINEAR);
                break;
        }
        return "UNKNOWN";  // line should never be reached;
        // it's here to silence compiler warnings
    };
};

//------------------------------------------------------------------------------------
// Refinement of SetGetTemplate<LongVec1d> defines only how to get
// a LongVec1d value from string input. All classes setting/getting
// a LongVec1d value should inherit from this one.
class SetGetLongVec1d : public SetGetTemplate<LongVec1d>
{
  public:
    SetGetLongVec1d(const std::string & key)
        : SetGetTemplate<LongVec1d>(key) {};
    virtual ~SetGetLongVec1d() {};
    virtual LongVec1d  GetValFromString(UIVars&, string input)
    {   return ProduceLongVec1dOrBarf(input); };
};

//------------------------------------------------------------------------------------
// Refinement of SetGetTemplate<ProftypeVec1d> defines only how to get
// a ProftypeVec1d value from string input. All classes setting/getting
// a ProftypeVec1d value should inherit from this one.
class SetGetProftypeVec1d : public SetGetTemplate<ProftypeVec1d>
{
  public:
    SetGetProftypeVec1d(const std::string & key)
        : SetGetTemplate<ProftypeVec1d>(key) {};
    virtual ~SetGetProftypeVec1d() {};
    virtual ProftypeVec1d  GetValFromString(UIVars&, string input)
    {   return ProduceProftypeVec1dOrBarf(input); };
};

//------------------------------------------------------------------------------------
// Refinement of SetGetBool which prints "Enabled" for
// a true value and "Disabled" for a false one
class SetGetBoolEnabled : public SetGetBool
{
  public:
    SetGetBoolEnabled(const std::string & key) : SetGetBool(key) {};
    virtual ~SetGetBoolEnabled() {};
    virtual std::string MakePrintString(UIVars&, bool val)
    {
        if(val) return "Enabled";
        return "Disabled";
    };
};

//------------------------------------------------------------------------------------
// Refinement of SetGetBool which prints "On" for
// a true value and "Off" for a false one
class SetGetBoolOnOff : public SetGetBool
{
  public:
    SetGetBoolOnOff(const std::string & key) : SetGetBool(key) {};
    virtual ~SetGetBoolOnOff() {};
    virtual std::string MakePrintString(UIVars&, bool val)
    {
        if(val) return "On";
        return "Off";
    };
};

//------------------------------------------------------------------------------------
// Refinement of SetGetBool which prints "Write" for
// a true value and "Read" for a false one
class SetGetBoolReadWrite : public SetGetBool
{
  public:
    SetGetBoolReadWrite(const std::string & key) : SetGetBool(key) {};
    virtual ~SetGetBoolReadWrite() {};
    virtual std::string MakePrintString(UIVars&, bool val)
    {
        if(val) return "Write";
        return "Read";
    };
};

class SetGetNoval : public SetGetTemplate<noval>
{
  public:
    SetGetNoval(const std::string & key)
        : SetGetTemplate<noval>(key) {};
    virtual ~SetGetNoval() {};
    virtual noval Get(UIVars&, UIId) { return noval_none;};
    virtual noval GetValFromString(UIVars&, string)
    { return noval_none;};
    virtual std::string NextToggleValue(UIVars&, UIId)
    { return ToString(noval_none);};
};

class SetGetProftypeSeries : public SetGetProftype
{
  public:
    SetGetProftypeSeries(const std::string & key)
        : SetGetProftype(key) {};
    virtual ~SetGetProftypeSeries() {};
};

#endif  // SETGET_H

//____________________________________________________________________________________
