// $Id: traitmodel_interface.cpp,v 1.8 2018/01/03 21:33:05 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 "traitmodel_interface.h"
#include "registry.h"
#include "ui_strings.h"
#include "ui_regid.h"
#include "ui_vars.h"

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

uiTraitModelName::uiTraitModelName()
    : GetString(uistr::traitModelName)
{
}

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

uiTraitModelName::~uiTraitModelName()
{
}

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

string uiTraitModelName::Get(UIVars& vars, UIId id)
{
    UIRegId regID(id, vars);
    return vars.traitmodels.GetName(regID);
}

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

SetRangepair::SetRangepair(const string& key)
    : SetGetTemplate<rangepair>(key)
{
}

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

SetRangepair::~SetRangepair()
{
}

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

rangepair SetRangepair::Get(UIVars& vars, UIId id)
{
    assert(false);
    throw implementation_error("Shouldn't be able to 'Get' anything from this interface");
};

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

rangepair SetRangepair::GetValFromString(UIVars& vars, string val)
{
    string::size_type colonpos = val.rfind(":");
    string firstnum = val;
    if (colonpos != string::npos)
    {
        firstnum.erase(colonpos, firstnum.size()-colonpos);
    }
    long int first = ProduceLongOrBarf(firstnum);
    long int second = first;
    if (colonpos != string::npos)
    {
        string secondnum = val;
        secondnum.erase(0,colonpos+1);
        second = ProduceLongOrBarf(secondnum);
    }
    if (first > second)
    {
        throw data_error("The second value in the range must be larger than the first.");
    }
    if (registry.GetConvertOutputToEliminateZeroes() && ((first == 0) || (second == 0)))
    {
        throw data_error("We assume that because you had no '0's for any map positions, your data follows the"
                         " traditional biologist convention of not having a site 0, and placing site -1 next"
                         " to site 1.  If this is incorrect, you must edit your LAMARC input file to set the"
                         " '<convert_output_to_eliminate_zeroes>' tag to 'false'.");
    }
    //Now make it open-ended.
    second++;
    return ToSequentialIfNeeded(std::make_pair(first, second));
}

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

uiAddRangeForTraitModel::uiAddRangeForTraitModel()
    : SetRangepair(uistr::addRangeForTraitModel)
{
}

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

uiAddRangeForTraitModel::~uiAddRangeForTraitModel()
{
}

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

void uiAddRangeForTraitModel::Set(UIVars& vars, UIId id, rangepair val)
{
    UIRegId regID(id, vars);
    vars.traitmodels.AddRange(regID, val);
}

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

uiRemoveRangeForTraitModel::uiRemoveRangeForTraitModel()
    : SetRangepair(uistr::removeRangeForTraitModel)
{
}

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

uiRemoveRangeForTraitModel::~uiRemoveRangeForTraitModel()
{
}

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

void uiRemoveRangeForTraitModel::Set(UIVars& vars, UIId id, rangepair val)
{
    UIRegId regID(id, vars);
    vars.traitmodels.RemoveRange(regID, val);
}

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

uiSetTraitModelRangeToPoint::uiSetTraitModelRangeToPoint()
    : SetGetLong(uistr::traitModelRangeToPoint)
{
}

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

uiSetTraitModelRangeToPoint::~uiSetTraitModelRangeToPoint()
{
}

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

void uiSetTraitModelRangeToPoint::Set(UIVars& vars, UIId id, long int val)
{
    UIRegId regID(id, vars);
    if (registry.GetConvertOutputToEliminateZeroes() && val == 0)
    {
        throw data_error("We assume that because you had no '0's for any map positions, your data follows"
                         " the traditional biologist convention of not having a site 0, and placing site"
                         " -1 next to site 1.  If this is incorrect, you must edit your LAMARC input file"
                         " to set the 'convert_output_to_eliminate_zeroes' tag to 'false'.");
    }
    val = ToSequentialIfNeeded(val);
    vars.traitmodels.SetRangeToPoint(regID, val);
}

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

long int uiSetTraitModelRangeToPoint::Get(UIVars& vars, UIId id)
{
    assert(false);
    throw implementation_error("Shouldn't be able to 'Get' anything from this interface");
}

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

uiValidMovingLoci::uiValidMovingLoci()
    : GetUIIdVec1d(uistr::validMovingLoci)
{
}

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

uiValidMovingLoci::~uiValidMovingLoci()
{
}

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

UIIdVec1d uiValidMovingLoci::Get(UIVars& vars, UIId id)
{
    vector<UIRegId> regIDs = vars.traitmodels.GetRegIDs();
    UIIdVec1d uiIDs;
    for (vector<UIRegId>::iterator regID = regIDs.begin(); regID != regIDs.end(); regID++)
    {
        UIId id(regID->GetRegion(), regID->GetLocus());
        uiIDs.push_back(id);
    }
    return uiIDs;
}

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

uiTraitModelFloat::uiTraitModelFloat()
    : SetGetNoval(uistr::traitAnalysisFloat)
{
}

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

uiTraitModelFloat::~uiTraitModelFloat()
{
}

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

void uiTraitModelFloat::Set(UIVars& vars, UIId id,noval val)
{
    UIRegId regID(id, vars);
    vars.traitmodels.SetAnalysisType(regID, mloc_mapfloat);
}

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

uiTraitModelJump::uiTraitModelJump()
    : SetGetNoval(uistr::traitAnalysisJump)
{
}

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

uiTraitModelJump::~uiTraitModelJump()
{
}

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

void uiTraitModelJump::Set(UIVars& vars, UIId id,noval val)
{
    UIRegId regID(id, vars);
    vars.traitmodels.SetAnalysisType(regID, mloc_mapjump);
}

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

uiTraitModelData::uiTraitModelData()
    : SetGetNoval(uistr::traitAnalysisData)
{
}

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

uiTraitModelData::~uiTraitModelData()
{
}

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

void uiTraitModelData::Set(UIVars& vars, UIId id,noval val)
{
    UIRegId regID(id, vars);
    vars.traitmodels.SetAnalysisType(regID, mloc_data);
}

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

uiTraitModelPartition::uiTraitModelPartition()
    : SetGetNoval(uistr::traitAnalysisPartition)
{
}

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

uiTraitModelPartition::~uiTraitModelPartition()
{
}

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

void uiTraitModelPartition::Set(UIVars& vars, UIId id,noval val)
{
    UIRegId regID(id, vars);
    vars.traitmodels.SetAnalysisType(regID, mloc_partition);
}

//____________________________________________________________________________________
