/*****************************************************************************
*
* Copyright (c) 2000 - 2018, Lawrence Livermore National Security, LLC
* Produced at the Lawrence Livermore National Laboratory
* LLNL-CODE-442911
* All rights reserved.
*
* This file is  part of VisIt. For  details, see https://visit.llnl.gov/.  The
* full copyright notice is contained in the file COPYRIGHT located at the root
* of the VisIt distribution or at http://www.llnl.gov/visit/copyright.html.
*
* Redistribution  and  use  in  source  and  binary  forms,  with  or  without
* modification, are permitted provided that the following conditions are met:
*
*  - Redistributions of  source code must  retain the above  copyright notice,
*    this list of conditions and the disclaimer below.
*  - Redistributions in binary form must reproduce the above copyright notice,
*    this  list of  conditions  and  the  disclaimer (as noted below)  in  the
*    documentation and/or other materials provided with the distribution.
*  - Neither the name of  the LLNS/LLNL nor the names of  its contributors may
*    be used to endorse or promote products derived from this software without
*    specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT  HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR  IMPLIED WARRANTIES, INCLUDING,  BUT NOT  LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND  FITNESS FOR A PARTICULAR  PURPOSE
* ARE  DISCLAIMED. IN  NO EVENT  SHALL LAWRENCE  LIVERMORE NATIONAL  SECURITY,
* LLC, THE  U.S.  DEPARTMENT OF  ENERGY  OR  CONTRIBUTORS BE  LIABLE  FOR  ANY
* DIRECT,  INDIRECT,   INCIDENTAL,   SPECIAL,   EXEMPLARY,  OR   CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT  LIMITED TO, PROCUREMENT OF  SUBSTITUTE GOODS OR
* SERVICES; LOSS OF  USE, DATA, OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER
* CAUSED  AND  ON  ANY  THEORY  OF  LIABILITY,  WHETHER  IN  CONTRACT,  STRICT
* LIABILITY, OR TORT  (INCLUDING NEGLIGENCE OR OTHERWISE)  ARISING IN ANY  WAY
* OUT OF THE  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
*****************************************************************************/

#include <BoxAttributes.h>
#include <DataNode.h>
#include <BoxExtents.h>

//
// Enum conversion methods for BoxAttributes::Amount
//

static const char *Amount_strings[] = {
"Some", "All"};

std::string
BoxAttributes::Amount_ToString(BoxAttributes::Amount t)
{
    int index = int(t);
    if(index < 0 || index >= 2) index = 0;
    return Amount_strings[index];
}

std::string
BoxAttributes::Amount_ToString(int t)
{
    int index = (t < 0 || t >= 2) ? 0 : t;
    return Amount_strings[index];
}

bool
BoxAttributes::Amount_FromString(const std::string &s, BoxAttributes::Amount &val)
{
    val = BoxAttributes::Some;
    for(int i = 0; i < 2; ++i)
    {
        if(s == Amount_strings[i])
        {
            val = (Amount)i;
            return true;
        }
    }
    return false;
}

// ****************************************************************************
// Method: BoxAttributes::BoxAttributes
//
// Purpose: 
//   Init utility for the BoxAttributes class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//   
// ****************************************************************************

void BoxAttributes::Init()
{
    amount = Some;
    minx = 0;
    maxx = 1;
    miny = 0;
    maxy = 1;
    minz = 0;
    maxz = 1;
    inverse = false;

    BoxAttributes::SelectAll();
}

// ****************************************************************************
// Method: BoxAttributes::BoxAttributes
//
// Purpose: 
//   Copy utility for the BoxAttributes class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//   
// ****************************************************************************

void BoxAttributes::Copy(const BoxAttributes &obj)
{
    amount = obj.amount;
    minx = obj.minx;
    maxx = obj.maxx;
    miny = obj.miny;
    maxy = obj.maxy;
    minz = obj.minz;
    maxz = obj.maxz;
    inverse = obj.inverse;

    BoxAttributes::SelectAll();
}

// Type map format string
const char *BoxAttributes::TypeMapFormatString = BOXATTRIBUTES_TMFS;
const AttributeGroup::private_tmfs_t BoxAttributes::TmfsStruct = {BOXATTRIBUTES_TMFS};


// ****************************************************************************
// Method: BoxAttributes::BoxAttributes
//
// Purpose: 
//   Default constructor for the BoxAttributes class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//   
// ****************************************************************************

BoxAttributes::BoxAttributes() : 
    AttributeSubject(BoxAttributes::TypeMapFormatString)
{
    BoxAttributes::Init();
}

// ****************************************************************************
// Method: BoxAttributes::BoxAttributes
//
// Purpose: 
//   Constructor for the derived classes of BoxAttributes class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//   
// ****************************************************************************

BoxAttributes::BoxAttributes(private_tmfs_t tmfs) : 
    AttributeSubject(tmfs.tmfs)
{
    BoxAttributes::Init();
}

// ****************************************************************************
// Method: BoxAttributes::BoxAttributes
//
// Purpose: 
//   Copy constructor for the BoxAttributes class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//   
// ****************************************************************************

BoxAttributes::BoxAttributes(const BoxAttributes &obj) : 
    AttributeSubject(BoxAttributes::TypeMapFormatString)
{
    BoxAttributes::Copy(obj);
}

// ****************************************************************************
// Method: BoxAttributes::BoxAttributes
//
// Purpose: 
//   Copy constructor for derived classes of the BoxAttributes class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//   
// ****************************************************************************

BoxAttributes::BoxAttributes(const BoxAttributes &obj, private_tmfs_t tmfs) : 
    AttributeSubject(tmfs.tmfs)
{
    BoxAttributes::Copy(obj);
}

// ****************************************************************************
// Method: BoxAttributes::~BoxAttributes
//
// Purpose: 
//   Destructor for the BoxAttributes class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//   
// ****************************************************************************

BoxAttributes::~BoxAttributes()
{
    // nothing here
}

// ****************************************************************************
// Method: BoxAttributes::operator = 
//
// Purpose: 
//   Assignment operator for the BoxAttributes class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//   
// ****************************************************************************

BoxAttributes& 
BoxAttributes::operator = (const BoxAttributes &obj)
{
    if (this == &obj) return *this;

    BoxAttributes::Copy(obj);

    return *this;
}

// ****************************************************************************
// Method: BoxAttributes::operator == 
//
// Purpose: 
//   Comparison operator == for the BoxAttributes class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//   
// ****************************************************************************

bool
BoxAttributes::operator == (const BoxAttributes &obj) const
{
    // Create the return value
    return ((amount == obj.amount) &&
            (minx == obj.minx) &&
            (maxx == obj.maxx) &&
            (miny == obj.miny) &&
            (maxy == obj.maxy) &&
            (minz == obj.minz) &&
            (maxz == obj.maxz) &&
            (inverse == obj.inverse));
}

// ****************************************************************************
// Method: BoxAttributes::operator != 
//
// Purpose: 
//   Comparison operator != for the BoxAttributes class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//   
// ****************************************************************************

bool
BoxAttributes::operator != (const BoxAttributes &obj) const
{
    return !(this->operator == (obj));
}

// ****************************************************************************
// Method: BoxAttributes::TypeName
//
// Purpose: 
//   Type name method for the BoxAttributes class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//   
// ****************************************************************************

const std::string
BoxAttributes::TypeName() const
{
    return "BoxAttributes";
}

// ****************************************************************************
// Method: BoxAttributes::CopyAttributes
//
// Purpose: 
//   CopyAttributes method for the BoxAttributes class.
//
// Programmer: Brad Whitlock
// Creation:   Tue Oct 29 08:57:18 PDT 2002
//
// Modifications:
//
// ****************************************************************************

bool
BoxAttributes::CopyAttributes(const AttributeGroup *atts)
{
    bool retval = false;

    if(TypeName() == atts->TypeName())
    {
        // Call assignment operator.
        const BoxAttributes *tmp = (const BoxAttributes *)atts;
        *this = *tmp;
        retval = true;
    }
    else if(atts->TypeName() == "BoxExtents")
    {
        const BoxExtents *tmp = (const BoxExtents *)atts;
        const double *extents = tmp->GetExtents();
        SetMinx(extents[0]);
        SetMaxx(extents[1]);
        SetMiny(extents[2]);
        SetMaxy(extents[3]);
        SetMinz(extents[4]);
        SetMaxz(extents[5]);
        retval = true;
    }

    return retval;
}

// ****************************************************************************
// Method: BoxAttributes::CreateCompatible
//
// Purpose: 
//   Creates an object of the specified type initialized with the attributes
//   from this object.
//
// Arguments:
//   tname : The typename of the object that we want to create.
//
// Returns:    A new object of the type specified by tname or 0.
//
// Note:       
//
// Programmer: Brad Whitlock
// Creation:   Tue Oct 29 08:57:46 PDT 2002
//
// Modifications:
//   
// ****************************************************************************

AttributeSubject *
BoxAttributes::CreateCompatible(const std::string &tname) const
{
    AttributeSubject *retval = 0;

    if(TypeName() == tname)
    {
        retval = new BoxAttributes(*this);
    }
    else if(tname == "BoxExtents")
    {
        BoxExtents *b = new BoxExtents;
        double extents[6];
        extents[0] = minx;
        extents[1] = maxx;
        extents[2] = miny;
        extents[3] = maxy;
        extents[4] = minz;
        extents[5] = maxz;
        b->SetExtents(extents);

        retval = b;
    }

    return retval;
}

// ****************************************************************************
// Method: BoxAttributes::NewInstance
//
// Purpose: 
//   NewInstance method for the BoxAttributes class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//   
// ****************************************************************************

AttributeSubject *
BoxAttributes::NewInstance(bool copy) const
{
    AttributeSubject *retval = 0;
    if(copy)
        retval = new BoxAttributes(*this);
    else
        retval = new BoxAttributes;

    return retval;
}

// ****************************************************************************
// Method: BoxAttributes::SelectAll
//
// Purpose: 
//   Selects all attributes.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//   
// ****************************************************************************

void
BoxAttributes::SelectAll()
{
    Select(ID_amount,  (void *)&amount);
    Select(ID_minx,    (void *)&minx);
    Select(ID_maxx,    (void *)&maxx);
    Select(ID_miny,    (void *)&miny);
    Select(ID_maxy,    (void *)&maxy);
    Select(ID_minz,    (void *)&minz);
    Select(ID_maxz,    (void *)&maxz);
    Select(ID_inverse, (void *)&inverse);
}

///////////////////////////////////////////////////////////////////////////////
// Persistence methods
///////////////////////////////////////////////////////////////////////////////

// ****************************************************************************
// Method: BoxAttributes::CreateNode
//
// Purpose: 
//   This method creates a DataNode representation of the object so it can be saved to a config file.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//   
// ****************************************************************************

bool
BoxAttributes::CreateNode(DataNode *parentNode, bool completeSave, bool forceAdd)
{
    if(parentNode == 0)
        return false;

    BoxAttributes defaultObject;
    bool addToParent = false;
    // Create a node for BoxAttributes.
    DataNode *node = new DataNode("BoxAttributes");

    if(completeSave || !FieldsEqual(ID_amount, &defaultObject))
    {
        addToParent = true;
        node->AddNode(new DataNode("amount", Amount_ToString(amount)));
    }

    if(completeSave || !FieldsEqual(ID_minx, &defaultObject))
    {
        addToParent = true;
        node->AddNode(new DataNode("minx", minx));
    }

    if(completeSave || !FieldsEqual(ID_maxx, &defaultObject))
    {
        addToParent = true;
        node->AddNode(new DataNode("maxx", maxx));
    }

    if(completeSave || !FieldsEqual(ID_miny, &defaultObject))
    {
        addToParent = true;
        node->AddNode(new DataNode("miny", miny));
    }

    if(completeSave || !FieldsEqual(ID_maxy, &defaultObject))
    {
        addToParent = true;
        node->AddNode(new DataNode("maxy", maxy));
    }

    if(completeSave || !FieldsEqual(ID_minz, &defaultObject))
    {
        addToParent = true;
        node->AddNode(new DataNode("minz", minz));
    }

    if(completeSave || !FieldsEqual(ID_maxz, &defaultObject))
    {
        addToParent = true;
        node->AddNode(new DataNode("maxz", maxz));
    }

    if(completeSave || !FieldsEqual(ID_inverse, &defaultObject))
    {
        addToParent = true;
        node->AddNode(new DataNode("inverse", inverse));
    }


    // Add the node to the parent node.
    if(addToParent || forceAdd)
        parentNode->AddNode(node);
    else
        delete node;

    return (addToParent || forceAdd);
}

// ****************************************************************************
// Method: BoxAttributes::SetFromNode
//
// Purpose: 
//   This method sets attributes in this object from values in a DataNode representation of the object.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//   
// ****************************************************************************

void
BoxAttributes::SetFromNode(DataNode *parentNode)
{
    if(parentNode == 0)
        return;

    DataNode *searchNode = parentNode->GetNode("BoxAttributes");
    if(searchNode == 0)
        return;

    DataNode *node;
    if((node = searchNode->GetNode("amount")) != 0)
    {
        // Allow enums to be int or string in the config file
        if(node->GetNodeType() == INT_NODE)
        {
            int ival = node->AsInt();
            if(ival >= 0 && ival < 2)
                SetAmount(Amount(ival));
        }
        else if(node->GetNodeType() == STRING_NODE)
        {
            Amount value;
            if(Amount_FromString(node->AsString(), value))
                SetAmount(value);
        }
    }
    if((node = searchNode->GetNode("minx")) != 0)
        SetMinx(node->AsDouble());
    if((node = searchNode->GetNode("maxx")) != 0)
        SetMaxx(node->AsDouble());
    if((node = searchNode->GetNode("miny")) != 0)
        SetMiny(node->AsDouble());
    if((node = searchNode->GetNode("maxy")) != 0)
        SetMaxy(node->AsDouble());
    if((node = searchNode->GetNode("minz")) != 0)
        SetMinz(node->AsDouble());
    if((node = searchNode->GetNode("maxz")) != 0)
        SetMaxz(node->AsDouble());
    if((node = searchNode->GetNode("inverse")) != 0)
        SetInverse(node->AsBool());
}

///////////////////////////////////////////////////////////////////////////////
// Set property methods
///////////////////////////////////////////////////////////////////////////////

void
BoxAttributes::SetAmount(BoxAttributes::Amount amount_)
{
    amount = amount_;
    Select(ID_amount, (void *)&amount);
}

void
BoxAttributes::SetMinx(double minx_)
{
    minx = minx_;
    Select(ID_minx, (void *)&minx);
}

void
BoxAttributes::SetMaxx(double maxx_)
{
    maxx = maxx_;
    Select(ID_maxx, (void *)&maxx);
}

void
BoxAttributes::SetMiny(double miny_)
{
    miny = miny_;
    Select(ID_miny, (void *)&miny);
}

void
BoxAttributes::SetMaxy(double maxy_)
{
    maxy = maxy_;
    Select(ID_maxy, (void *)&maxy);
}

void
BoxAttributes::SetMinz(double minz_)
{
    minz = minz_;
    Select(ID_minz, (void *)&minz);
}

void
BoxAttributes::SetMaxz(double maxz_)
{
    maxz = maxz_;
    Select(ID_maxz, (void *)&maxz);
}

void
BoxAttributes::SetInverse(bool inverse_)
{
    inverse = inverse_;
    Select(ID_inverse, (void *)&inverse);
}

///////////////////////////////////////////////////////////////////////////////
// Get property methods
///////////////////////////////////////////////////////////////////////////////

BoxAttributes::Amount
BoxAttributes::GetAmount() const
{
    return Amount(amount);
}

double
BoxAttributes::GetMinx() const
{
    return minx;
}

double
BoxAttributes::GetMaxx() const
{
    return maxx;
}

double
BoxAttributes::GetMiny() const
{
    return miny;
}

double
BoxAttributes::GetMaxy() const
{
    return maxy;
}

double
BoxAttributes::GetMinz() const
{
    return minz;
}

double
BoxAttributes::GetMaxz() const
{
    return maxz;
}

bool
BoxAttributes::GetInverse() const
{
    return inverse;
}

///////////////////////////////////////////////////////////////////////////////
// Keyframing methods
///////////////////////////////////////////////////////////////////////////////

// ****************************************************************************
// Method: BoxAttributes::GetFieldName
//
// Purpose: 
//   This method returns the name of a field given its index.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//   
// ****************************************************************************

std::string
BoxAttributes::GetFieldName(int index) const
{
    switch (index)
    {
    case ID_amount:  return "amount";
    case ID_minx:    return "minx";
    case ID_maxx:    return "maxx";
    case ID_miny:    return "miny";
    case ID_maxy:    return "maxy";
    case ID_minz:    return "minz";
    case ID_maxz:    return "maxz";
    case ID_inverse: return "inverse";
    default:  return "invalid index";
    }
}

// ****************************************************************************
// Method: BoxAttributes::GetFieldType
//
// Purpose: 
//   This method returns the type of a field given its index.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//   
// ****************************************************************************

AttributeGroup::FieldType
BoxAttributes::GetFieldType(int index) const
{
    switch (index)
    {
    case ID_amount:  return FieldType_enum;
    case ID_minx:    return FieldType_double;
    case ID_maxx:    return FieldType_double;
    case ID_miny:    return FieldType_double;
    case ID_maxy:    return FieldType_double;
    case ID_minz:    return FieldType_double;
    case ID_maxz:    return FieldType_double;
    case ID_inverse: return FieldType_bool;
    default:  return FieldType_unknown;
    }
}

// ****************************************************************************
// Method: BoxAttributes::GetFieldTypeName
//
// Purpose: 
//   This method returns the name of a field type given its index.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//   
// ****************************************************************************

std::string
BoxAttributes::GetFieldTypeName(int index) const
{
    switch (index)
    {
    case ID_amount:  return "enum";
    case ID_minx:    return "double";
    case ID_maxx:    return "double";
    case ID_miny:    return "double";
    case ID_maxy:    return "double";
    case ID_minz:    return "double";
    case ID_maxz:    return "double";
    case ID_inverse: return "bool";
    default:  return "invalid index";
    }
}

// ****************************************************************************
// Method: BoxAttributes::FieldsEqual
//
// Purpose: 
//   This method compares two fields and return true if they are equal.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//   
// ****************************************************************************

bool
BoxAttributes::FieldsEqual(int index_, const AttributeGroup *rhs) const
{
    const BoxAttributes &obj = *((const BoxAttributes*)rhs);
    bool retval = false;
    switch (index_)
    {
    case ID_amount:
        {  // new scope
        retval = (amount == obj.amount);
        }
        break;
    case ID_minx:
        {  // new scope
        retval = (minx == obj.minx);
        }
        break;
    case ID_maxx:
        {  // new scope
        retval = (maxx == obj.maxx);
        }
        break;
    case ID_miny:
        {  // new scope
        retval = (miny == obj.miny);
        }
        break;
    case ID_maxy:
        {  // new scope
        retval = (maxy == obj.maxy);
        }
        break;
    case ID_minz:
        {  // new scope
        retval = (minz == obj.minz);
        }
        break;
    case ID_maxz:
        {  // new scope
        retval = (maxz == obj.maxz);
        }
        break;
    case ID_inverse:
        {  // new scope
        retval = (inverse == obj.inverse);
        }
        break;
    default: retval = false;
    }

    return retval;
}

///////////////////////////////////////////////////////////////////////////////
// User-defined methods.
///////////////////////////////////////////////////////////////////////////////

