// $Id: ui_vars.cpp,v 1.27 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 "datapack.h"
#include "defaults.h"
#include "ui_vars.h"

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

UIVars::UIVars(DataPack& datapack, string fileName, UIInterface* myui)
    :   ui(myui),
        chains(this), //no prerequisites
        userparams( this,
                    fileName), //no prerequisites
        datapackplus(this,
                     datapack), //no prerequisites
        datamodel(this,
                  datapack.GetNRegions(),datapack.GetNMaxLoci()),
        //datamodel requires datapackplus
        traitmodels(this),
        //traitmodels also requires datapackplus
        forces(     this,
                    datapackplus.GetNCrossPartitions(),
                    datapackplus.GetNPartitionsByForceType(force_MIG),
                    datapackplus.GetNPartitionsByForceType(force_DIVMIG),
                    datapackplus.GetNPartitionsByForceType(force_DISEASE),
                    datapack.CanMeasureRecombination())
        //forces requires both datapackplus and datamodel.  It might
        // eventually require traitmodels, too!  So.  Definitely last.

        // WARNING!!
        // Here we're loading up the UIVars with information coming from
        // the datapack. However, here in the constructor is the only
        // time we should be doing anything directly from the DataPack.
        // After construction time, access needed to DataPack structures
        // by the UI should go through the UIVarsDataPackPlus class.
        // Ideally, we'd like to refactor this later so that there is
        // an "early" and a "late" version of the DataPack. This restriction
        // on access is the first step in supporting that refactor.
{
}

UIVars::UIVars(const UIVars& vars)
    :   ui(vars.ui),
        chains(this,vars.chains),
        userparams(this,vars.userparams),
        datapackplus(this,vars.datapackplus),
        datamodel(this,vars.datamodel),
        traitmodels(this, vars.traitmodels),
        forces(this,vars.forces)
{
}

UIVars::~UIVars()
{
}

string UIVars::GetParamNameWithConstraint(force_type ftype, long pindex,
                                          bool doLongName) const
{
    //This function has to be here because it uses both forces and datapackplus.

    string shortname = datapackplus.GetParamName(ftype, pindex, false);
    string longname = datapackplus.GetParamName(ftype, pindex, true);
    long gindex = forces.ParamInGroup(ftype, pindex);
    if (gindex != FLAGLONG)
    {
        LongVec1d gpindexes = forces.GetGroupParamList(ftype, gindex);
        shortname = "";
        longname = "";
        string::size_type commapos = string::npos;
        //This is guaranteed to be overwritten.
        for (unsigned long gpnum=0; gpnum<gpindexes.size(); gpnum++)
        {
            commapos = longname.rfind(",");
            shortname += datapackplus.GetParamName(ftype, gpindexes[gpnum], false)
                + "/";
            longname +=  datapackplus.GetParamName(ftype, gpindexes[gpnum], true)
                + ", ";
        }
        shortname.erase(shortname.size()-1,1);
        longname.erase(longname.size()-2,2);
        if (gpindexes.size()==2)
        {
            longname.replace(commapos,1," and");
            longname.append(" (both constrained to ");
        }
        else if (gpindexes.size() > 2)
        {
            longname.insert(commapos+1," and");
            longname.append(" (all constrained to ");
        }
        else
        {
            assert (gpindexes.size() == 1);
            longname.append(" (the only current member of a potential group, which would be constrained to ");
        }
    }

    ParamStatus pstat(forces.GetParamstatus(ftype,pindex));
    longname.append(pstat.ConstraintDescription(gindex));

    if (doLongName) return longname;
    return shortname;
}

//____________________________________________________________________________________
