// $Id: datamodel_interface.cpp,v 1.40 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 */


#include <cassert>
#include <string>

#include "datamodel_interface.h"
#include "lamarc_strings.h"     // for lamarcmenu::calcPerLocus and ::calculated
#include "ui_regid.h"
#include "ui_strings.h"
#include "ui_vars.h"
#include "vectorx.h"
#include "xml_strings.h"

using std::string;

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

long uiLociCount::Get(UIVars& vars, UIId id)
{
    return vars.datapackplus.GetNumLoci(id.GetIndex1());
}

uiLociCount::uiLociCount()
    : GetLong(uistr::lociCount)
{
}

uiLociCount::~uiLociCount()
{
}

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

string uiLocusName::Get(UIVars& vars, UIId id)
{
    return vars.datapackplus.GetLocusName(id.GetIndex1(),id.GetIndex2());

}

uiLocusName::uiLocusName()
    : GetString(uistr::locusName)
{
}

uiLocusName::~uiLocusName()
{
}

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

string uiRegionName::Get(UIVars& vars, UIId id)
{
    return vars.datapackplus.GetRegionName(id.GetIndex1());

}

uiRegionName::uiRegionName()
    : GetString(uistr::regionName)
{
}

uiRegionName::~uiRegionName()
{
}

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

bool uiFreqsFromData::Get(UIVars& vars, UIId id)
{
    return vars.datamodel.GetCalcFreqsFromData(UIRegId(id, vars));
}

void uiFreqsFromData::Set(UIVars& vars, UIId id, bool val)
{
    vars.datamodel.SetCalcFreqsFromData(val,UIRegId(id, vars));
}

uiFreqsFromData::uiFreqsFromData()
    : SetGetBool(uistr::freqsFromData)
{
}

uiFreqsFromData::~uiFreqsFromData()
{
}

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

uiDataType::uiDataType()
    : GetDataType(uistr::dataType)
{
}

uiDataType::~uiDataType()
{
}

data_type uiDataType::Get(UIVars& vars, UIId id)
{
    return vars.datamodel.GetDataType(UIRegId(id,vars));
}

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

DoubleVec1d uiGTRRates::Get(UIVars& vars, UIId id)
{
    DoubleVec1d gtrs(6);
    gtrs[0] = vars.datamodel.GetGTR_AC(UIRegId(id, vars));
    gtrs[1] = vars.datamodel.GetGTR_AG(UIRegId(id, vars));
    gtrs[2] = vars.datamodel.GetGTR_AT(UIRegId(id, vars));
    gtrs[3] = vars.datamodel.GetGTR_CG(UIRegId(id, vars));
    gtrs[4] = vars.datamodel.GetGTR_CT(UIRegId(id, vars));
    gtrs[5] = vars.datamodel.GetGTR_GT(UIRegId(id, vars));
    return gtrs;
}

uiGTRRates::uiGTRRates()
    : GetDoubleVec1d(uistr::gtrRates)
{
}

uiGTRRates::~uiGTRRates()
{
}

string uiGTRRates::GetPrintString(UIVars& vars, UIId id)
{
    DoubleVec1d gtrs = Get(vars, id);
    assert(gtrs.size() == 6);
    string vals = Pretty(gtrs[0],6);
    for (unsigned long i=1; i<gtrs.size(); i++)
    {
        vals += " " + Pretty(gtrs[i],6);
    }
    return vals;
}

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

double uiGTRRateAC::Get(UIVars& vars, UIId id)
{
    return vars.datamodel.GetGTR_AC(UIRegId(id, vars));
}

void uiGTRRateAC::Set(UIVars& vars, UIId id, double val)
{
    vars.datamodel.SetGTR_AC(val,UIRegId(id, vars));
}

uiGTRRateAC::uiGTRRateAC()
    : SetGetDouble(uistr::gtrRateAC)
{
}

uiGTRRateAC::~uiGTRRateAC()
{
}

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

double uiGTRRateAG::Get(UIVars& vars, UIId id)
{
    return vars.datamodel.GetGTR_AG(UIRegId(id, vars));
}

void uiGTRRateAG::Set(UIVars& vars, UIId id, double val)
{
    vars.datamodel.SetGTR_AG(val,UIRegId(id, vars));
}

uiGTRRateAG::uiGTRRateAG()
    : SetGetDouble(uistr::gtrRateAG)
{
}

uiGTRRateAG::~uiGTRRateAG()
{
}

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

double uiGTRRateAT::Get(UIVars& vars, UIId id)
{
    return vars.datamodel.GetGTR_AT(UIRegId(id, vars));
}

void uiGTRRateAT::Set(UIVars& vars, UIId id, double val)
{
    vars.datamodel.SetGTR_AT(val,UIRegId(id, vars));
}

uiGTRRateAT::uiGTRRateAT()
    : SetGetDouble(uistr::gtrRateAT)
{
}

uiGTRRateAT::~uiGTRRateAT()
{
}

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

double uiGTRRateCG::Get(UIVars& vars, UIId id)
{
    return vars.datamodel.GetGTR_CG(UIRegId(id, vars));
}

void uiGTRRateCG::Set(UIVars& vars, UIId id, double val)
{
    vars.datamodel.SetGTR_CG(val,UIRegId(id, vars));
}

uiGTRRateCG::uiGTRRateCG()
    : SetGetDouble(uistr::gtrRateCG)
{
}

uiGTRRateCG::~uiGTRRateCG()
{
}

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

double uiGTRRateCT::Get(UIVars& vars, UIId id)
{
    return vars.datamodel.GetGTR_CT(UIRegId(id, vars));
}

void uiGTRRateCT::Set(UIVars& vars, UIId id, double val)
{
    vars.datamodel.SetGTR_CT(val,UIRegId(id, vars));
}

uiGTRRateCT::uiGTRRateCT()
    : SetGetDouble(uistr::gtrRateCT)
{
}

uiGTRRateCT::~uiGTRRateCT()
{
}

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

double uiGTRRateGT::Get(UIVars& vars, UIId id)
{
    return vars.datamodel.GetGTR_GT(UIRegId(id, vars));
}

void uiGTRRateGT::Set(UIVars& vars, UIId id, double val)
{
    vars.datamodel.SetGTR_GT(val,UIRegId(id, vars));
}

uiGTRRateGT::uiGTRRateGT()
    : SetGetDouble(uistr::gtrRateGT)
{
}

uiGTRRateGT::~uiGTRRateGT()
{
}

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

DoubleVec1d uiBaseFrequencies::Get(UIVars& vars, UIId id)
{
    DoubleVec1d freqs(4);
    freqs[0] = vars.datamodel.GetFrequencyA(UIRegId(id, vars));
    freqs[1] = vars.datamodel.GetFrequencyC(UIRegId(id, vars));
    freqs[2] = vars.datamodel.GetFrequencyG(UIRegId(id, vars));
    freqs[3] = vars.datamodel.GetFrequencyT(UIRegId(id, vars));
    return freqs;
}

uiBaseFrequencies::uiBaseFrequencies()
    : GetDoubleVec1d(uistr::baseFrequencies)
{
}

uiBaseFrequencies::~uiBaseFrequencies()
{
}

string uiBaseFrequencies::GetPrintString(UIVars& vars, UIId id)
{
    UIRegId regId(id, vars);
    bool calculated = vars.datamodel.GetCalcFreqsFromData(regId);
    if(regId.GetRegion() == uiconst::GLOBAL_ID && calculated)
    {
        return lamarcmenu::calcPerLocus;
    }
    else
    {
        DoubleVec1d freqs = Get(vars, id);
        assert(freqs.size() == 4);
        string vals = Pretty(freqs[0], 6);
        for (unsigned long i=1; i<freqs.size(); i++)
        {
            vals += " " + Pretty(freqs[i], 6);
        }
        if(calculated)
        {
            vals += lamarcmenu::calculated;
        }
        return vals;
    }
}

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

double uiBaseFrequencyA::Get(UIVars& vars, UIId id)
{
    return vars.datamodel.GetFrequencyA(UIRegId(id, vars));
}

void uiBaseFrequencyA::Set(UIVars& vars, UIId id, double val)
{
    vars.datamodel.SetFrequencyA(val,UIRegId(id, vars));
}

uiBaseFrequencyA::uiBaseFrequencyA()
    : SetGetDouble(uistr::baseFrequencyA)
{
}

uiBaseFrequencyA::~uiBaseFrequencyA()
{
}

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

double uiBaseFrequencyC::Get(UIVars& vars, UIId id)
{
    return vars.datamodel.GetFrequencyC(UIRegId(id, vars));
}

void uiBaseFrequencyC::Set(UIVars& vars, UIId id, double val)
{
    vars.datamodel.SetFrequencyC(val,UIRegId(id, vars));
}

uiBaseFrequencyC::uiBaseFrequencyC()
    : SetGetDouble(uistr::baseFrequencyC)
{
}

uiBaseFrequencyC::~uiBaseFrequencyC()
{
}

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

double uiBaseFrequencyG::Get(UIVars& vars, UIId id)
{
    return vars.datamodel.GetFrequencyG(UIRegId(id, vars));
}

void uiBaseFrequencyG::Set(UIVars& vars, UIId id, double val)
{
    vars.datamodel.SetFrequencyG(val,UIRegId(id, vars));
}

uiBaseFrequencyG::uiBaseFrequencyG()
    : SetGetDouble(uistr::baseFrequencyG)
{
}

uiBaseFrequencyG::~uiBaseFrequencyG()
{
}

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

double uiBaseFrequencyT::Get(UIVars& vars, UIId id)
{
    return vars.datamodel.GetFrequencyT(UIRegId(id, vars));
}

void uiBaseFrequencyT::Set(UIVars& vars, UIId id, double val)
{
    vars.datamodel.SetFrequencyT(val,UIRegId(id, vars));
}

uiBaseFrequencyT::uiBaseFrequencyT()
    : SetGetDouble(uistr::baseFrequencyT)
{
}

uiBaseFrequencyT::~uiBaseFrequencyT()
{
}

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

model_type uiDataModel::Get(UIVars& vars, UIId id)
{
    return vars.datamodel.GetDataModelType(UIRegId(id, vars));
}

void uiDataModel::Set(UIVars& vars, UIId id, model_type val)
{
    vars.datamodel.SetDataModelType(val,UIRegId(id, vars));
}

string
uiDataModel::NextToggleValue(UIVars& vars, UIId id)
{
    ModelTypeVec1d legalModels = vars.datamodel.GetLegalDataModels(UIRegId(id, vars));
    if(legalModels.empty())
    {
        implementation_error e("No legal model type available");
        throw e;
    }
    model_type thisModel = vars.datamodel.GetDataModelType(UIRegId(id, vars));
    long index;
    long numModels = legalModels.size();
    // find thisModel in the list and grab the next one
    for(index = 0; index < numModels; index++)
    {
        if (legalModels[index] == thisModel)
        {
            return ToString(legalModels[(index + 1) % numModels]);
        }
    }
    // didn't find this model, but there is a legal one, so grab the first
    assert(false); //Why did we have an illegal data model to begin with?
    return ToString(legalModels[0]);
}

uiDataModel::uiDataModel()
    : SetGetModelType(uistr::dataModel)
{
}

uiDataModel::~uiDataModel()
{
}

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

StringVec1d uiDataModelReport::Get(UIVars& vars, UIId id)
{
    return vars.datamodel.GetDataModelReport(UIRegId(id, vars));
}

uiDataModelReport::uiDataModelReport()
    : GetStringVec1d(uistr::dataModelReport)
{
}

uiDataModelReport::~uiDataModelReport()
{
}

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

bool uiNormalization::Get(UIVars& vars, UIId id)
{
    return vars.datamodel.GetNormalization(UIRegId(id, vars));
}

void uiNormalization::Set(UIVars& vars, UIId id, bool val)
{
    vars.datamodel.SetNormalization(val,UIRegId(id, vars));
}

uiNormalization::uiNormalization()
    : SetGetBool(uistr::normalization)
{
}

uiNormalization::~uiNormalization()
{
}

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

double uiTTRatio::Get(UIVars& vars, UIId id)
{
    return vars.datamodel.GetTTRatio(UIRegId(id, vars));
}

void uiTTRatio::Set(UIVars& vars, UIId id, double val)
{
    vars.datamodel.SetTTRatio(val,UIRegId(id, vars));
}

uiTTRatio::uiTTRatio()
    : SetGetDouble(uistr::TTRatio)
{
}

uiTTRatio::~uiTTRatio()
{
}

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

double uiPerBaseErrorRate::Get(UIVars& vars, UIId id)
{
    return vars.datamodel.GetPerBaseErrorRate(UIRegId(id, vars));
}

void uiPerBaseErrorRate::Set(UIVars& vars, UIId id, double val)
{
    vars.datamodel.SetPerBaseErrorRate(val,UIRegId(id, vars));
}

uiPerBaseErrorRate::uiPerBaseErrorRate()
    : SetGetDouble(uistr::perBaseErrorRate)
{
}

uiPerBaseErrorRate::~uiPerBaseErrorRate()
{
}

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

double uiAlpha::Get(UIVars& vars, UIId id)
{
    return vars.datamodel.GetAlpha(UIRegId(id, vars));
}

void uiAlpha::Set(UIVars& vars, UIId id, double val)
{
    vars.datamodel.SetAlpha(val,UIRegId(id, vars));
}

string uiAlpha::Min(UIVars& vars, UIId id)
{
    return "zero";
}

string uiAlpha::Max(UIVars& vars, UIId id)
{
    return "one";
}

uiAlpha::uiAlpha()
    : SetGetDouble(uistr::alpha)
{
}

uiAlpha::~uiAlpha()
{
}

bool uiOptimizeAlpha::Get(UIVars& vars, UIId id)
{
    return vars.datamodel.GetOptimizeAlpha(UIRegId(id, vars));
}

void uiOptimizeAlpha::Set(UIVars& vars, UIId id, bool val)
{
    vars.datamodel.SetOptimizeAlpha(val,UIRegId(id, vars));
}

uiOptimizeAlpha::uiOptimizeAlpha()
    : SetGetBool(uistr::optimizeAlpha)
{
}

uiOptimizeAlpha::~uiOptimizeAlpha()
{
}

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

double uiAutoCorrelation::Get(UIVars& vars, UIId id)
{
    // NB: This gets the user (uninverted) value
    return vars.datamodel.GetAutoCorrelation(UIRegId(id, vars));
}

void uiAutoCorrelation::Set(UIVars& vars, UIId id, double val)
{
    // NB: This sets the user (uninverted) value
    vars.datamodel.SetAutoCorrelation(val,UIRegId(id, vars));
}

uiAutoCorrelation::uiAutoCorrelation()
    : SetGetDouble(uistr::autoCorrelation)
{
}

uiAutoCorrelation::~uiAutoCorrelation()
{
}

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

long uiCategoryCount::Get(UIVars& vars, UIId id)
{
    return vars.datamodel.GetNumCategories(UIRegId(id, vars));
}

void uiCategoryCount::Set(UIVars& vars, UIId id, long val)
{
    vars.datamodel.SetNumCategories(val,UIRegId(id, vars));
}

string uiCategoryCount::Min(UIVars& vars, UIId id)
{
    return "1";
}

string uiCategoryCount::Max(UIVars& vars, UIId id)
{
    return ToString(defaults::maxNumCategories);
}

uiCategoryCount::uiCategoryCount()
    : SetGetLong(uistr::categoryCount)
{
}

uiCategoryCount::~uiCategoryCount()
{
}

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

double uiCategoryProbability::Get(UIVars& vars, UIId id)
{
    return vars.datamodel.GetCategoryProbability(UIRegId(id, vars),id.GetIndex3());
}

void uiCategoryProbability::Set(UIVars& vars, UIId id, double val)
{
    vars.datamodel.SetCategoryProbability(val,UIRegId(id, vars),id.GetIndex3());
}

uiCategoryProbability::uiCategoryProbability()
    : SetGetDouble(uistr::categoryProbability)
{
}

uiCategoryProbability::~uiCategoryProbability()
{
}

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

double uiCategoryRate::Get(UIVars& vars, UIId id)
{
    return vars.datamodel.GetCategoryRate(UIRegId(id, vars),id.GetIndex3());
}

void uiCategoryRate::Set(UIVars& vars, UIId id, double val)
{
    vars.datamodel.SetCategoryRate(val,UIRegId(id, vars),id.GetIndex3());
}

uiCategoryRate::uiCategoryRate()
    : SetGetDouble(uistr::categoryRate)
{
}

uiCategoryRate::~uiCategoryRate()
{
}

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

double uiRelativeMuRate::Get(UIVars& vars, UIId id)
{
    return vars.datamodel.GetRelativeMuRate(UIRegId(id, vars));
}

void uiRelativeMuRate::Set(UIVars& vars, UIId id, double val)
{
    vars.datamodel.SetRelativeMuRate(val,UIRegId(id, vars));
}

uiRelativeMuRate::uiRelativeMuRate()
    : SetGetDouble(uistr::relativeMuRate)
{
}

uiRelativeMuRate::~uiRelativeMuRate()
{
}

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

void
uiUseGlobalDataModelForAll::Set(UIVars& vars, UIId id, noval val)
{
    vars.datamodel.SetAllRegionsToGlobalModel();
}

uiUseGlobalDataModelForAll::uiUseGlobalDataModelForAll()
    : SetGetNoval(uistr::useGlobalDataModelForAll)
{
}

uiUseGlobalDataModelForAll::~uiUseGlobalDataModelForAll()
{
}

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

bool
uiUseGlobalDataModelForOne::Get(UIVars& vars, UIId id)
{
    return vars.datamodel.GetUseGlobalModel(UIRegId(id, vars));
}

void
uiUseGlobalDataModelForOne::Set(UIVars& vars, UIId id, bool val)
{
    vars.datamodel.SetUseGlobalModel(val,UIRegId(id, vars));
}

uiUseGlobalDataModelForOne::uiUseGlobalDataModelForOne()
    : SetGetBool(uistr::useGlobalDataModelForOne)
{
}

uiUseGlobalDataModelForOne::~uiUseGlobalDataModelForOne()
{
}

//____________________________________________________________________________________
