// $Id: ui_id.cpp,v 1.12 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 "ui_id.h"
#include "ui_constants.h"

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

// an ID expressing a doubly indexed quantity
UIId::UIId(long index1, long index2, long index3)
    :
    m_hasForce(false),
    m_forceType(force_COAL),        // any force_type will do here as
    // long as it's the same value for
    // every UIId with m_hasForce == false
    // We picked force_COAL 'cause it's first
    m_index1(index1),
    m_index2(index2),
    m_index3(index3)
{
    assert(IndexesAreOkay());
}

// an ID expressing a force and a doubly indexed quantity
UIId::UIId(force_type force, long index1, long index2, long index3)
    :
    m_hasForce(true),
    m_forceType(force),
    m_index1(index1),
    m_index2(index2),
    m_index3(index3)
{
    assert(IndexesAreOkay());
}

bool UIId::IndexesAreOkay() const
{
    if (!(m_index1 >= 0 ||
          m_index1 == uiconst::NO_ID ||
          m_index1 == uiconst::GLOBAL_ID ||
          m_index1 == uiconst::GLOBAL_DATAMODEL_NUC_ID ||
          m_index1 == uiconst::GLOBAL_DATAMODEL_MSAT_ID ||
          m_index1 == uiconst::GLOBAL_DATAMODEL_KALLELE_ID))
    {
        return false;
    }
    if (!(m_index2 >= 0 || m_index2 == uiconst::NO_ID))
    {
        return false;
    }
    if (!(m_index3 >= 0 || m_index3 == uiconst::NO_ID))
    {
        return false;
    }
    return true;
}

force_type
UIId::GetForceType() const
{
    assert(m_hasForce);
    return m_forceType;
}

long
UIId::GetIndex1() const
{
    assert(HasIndex1());
    return m_index1;
}

long
UIId::GetIndex2() const
{
    assert(HasIndex1() && HasIndex2());
    return m_index2;
}

long
UIId::GetIndex3() const
{
    assert(HasIndex1() && HasIndex2() && HasIndex3());
    return m_index3;
}

bool
UIId::operator==(const UIId& id) const
{
    // note -- logically, the values of m_forceType shouldn't
    // need to be identical when m_hasForce is false. BUT,
    // we're always constructing UIId's to have m_forceType == force_COAL
    // when m_hasForce == false
    return (    m_hasForce  ==  id.m_hasForce
                &&  m_index1    ==  id.m_index1
                &&  m_index2    ==  id.m_index2
                &&  m_index3    ==  id.m_index3
                &&  m_forceType ==  id.m_forceType
        );
}

bool
UIId::HasForce() const
{
    return m_hasForce;
}

bool
UIId::HasIndex1() const
{
    return (m_index1 != uiconst::NO_ID);
}

bool
UIId::HasIndex2() const
{
    return (m_index2 != uiconst::NO_ID);
}

bool
UIId::HasIndex3() const
{
    return (m_index3 != uiconst::NO_ID);
}

UIId & NO_ID()
{
    static UIId no_id = UIId();
    return no_id;
};

UIId & GLOBAL_ID()
{
    static UIId global_id = UIId(uiconst::GLOBAL_ID);
    return global_id;
};

//____________________________________________________________________________________
