/***********************************************************************
    filename:   CEGUIPropertyHelper.cpp
    created:    6/7/2004
    author:     Paul D Turner

    purpose:    Implementation of PropertyHelper methods
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2006 Paul D Turner & The CEGUI Development Team
 *
 *   Permission is hereby granted, free of charge, to any person obtaining
 *   a copy of this software and associated documentation files (the
 *   "Software"), to deal in the Software without restriction, including
 *   without limitation the rights to use, copy, modify, merge, publish,
 *   distribute, sublicense, and/or sell copies of the Software, and to
 *   permit persons to whom the Software is furnished to do so, subject to
 *   the following conditions:
 *
 *   The above copyright notice and this permission notice shall be
 *   included in all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *   OTHER DEALINGS IN THE SOFTWARE.
 ***************************************************************************/
#include "CEGUIPropertyHelper.h"
#include "CEGUIImagesetManager.h"
#include "CEGUIImageset.h"
#include "CEGUIExceptions.h"

#include <cstdio>
#include <sstream>

#ifdef _MSC_VER
#define snprintf _snprintf
#endif

// Start of CEGUI namespace section
namespace CEGUI
{
float PropertyHelper::stringToFloat(const String& str)
{
    using namespace std;

    float val = 0;
    sscanf(str.c_str(), " %g", &val);

    return val;
}


uint PropertyHelper::stringToUint(const String& str)
{
    using namespace std;

    uint val = 0;
    sscanf(str.c_str(), " %u", &val);

    return val;
}


int PropertyHelper::stringToInt(const String& str)
{
    using namespace std;

    int val = 0;
    sscanf(str.c_str(), " %d", &val);

    return val;
}


bool PropertyHelper::stringToBool(const String& str)
{
    if ((str == "True") || (str == "true"))
    {
        return true;
    }
    else
    {
        return false;
    }

}


Size PropertyHelper::stringToSize(const String& str)
{
    using namespace std;

    Size val(0, 0);
    sscanf(str.c_str(), " w:%g h:%g", &val.d_width, &val.d_height);

    return val;
}


Point PropertyHelper::stringToPoint(const String& str)
{
    using namespace std;

    Point val(0, 0) ;
    sscanf(str.c_str(), " x:%g y:%g", &val.d_x, &val.d_y);

    return val;
}


Rect PropertyHelper::stringToRect(const String& str)
{
    using namespace std;

    Rect val(0, 0, 0, 0);
    sscanf(str.c_str(), " l:%g t:%g r:%g b:%g", &val.d_left, &val.d_top, &val.d_right, &val.d_bottom);

    return val;
}


const Image* PropertyHelper::stringToImage(const String& str)
{
    using namespace std;

    // handle empty string case
    if (str.empty())
        return 0;

    char imageSet[128];
    char imageName[128];

    sscanf(str.c_str(), " set:%127s image:%127s", imageSet, imageName);

    const Image* image;

    CEGUI_TRY
    {
        image = &ImagesetManager::getSingleton().get(imageSet).getImage(imageName);
    }
    CEGUI_CATCH(UnknownObjectException&)
    {
        image = 0;
    }

    return image;
}


UDim PropertyHelper::stringToUDim(const String& str)
{
    using namespace std;

    UDim ud;
    sscanf(str.c_str(), " { %g , %g }", &ud.d_scale, &ud.d_offset);

    return ud;
}


UVector2 PropertyHelper::stringToUVector2(const String& str)
{
    using namespace std;

    UVector2 uv;
    sscanf(str.c_str(), " { { %g , %g } , { %g , %g } }",
           &uv.d_x.d_scale, &uv.d_x.d_offset,
           &uv.d_y.d_scale, &uv.d_y.d_offset);

    return uv;
}


URect PropertyHelper::stringToURect(const String& str)
{
    using namespace std;

    URect ur;
    sscanf(
        str.c_str(),
        " { { %g , %g } , { %g , %g } , { %g , %g } , { %g , %g } }",
        &ur.d_min.d_x.d_scale, &ur.d_min.d_x.d_offset,
        &ur.d_min.d_y.d_scale, &ur.d_min.d_y.d_offset,
        &ur.d_max.d_x.d_scale, &ur.d_max.d_x.d_offset,
        &ur.d_max.d_y.d_scale, &ur.d_max.d_y.d_offset
    );

    return ur;
}

UBox PropertyHelper::stringToUBox(const String& str)
{
    using namespace std;

    UBox ret;
    sscanf(
        str.c_str(),
        " { top: { %g , %g } , left: { %g , %g } , bottom: { %g , %g } , right: { %g , %g } }",
        &ret.d_top.d_scale, &ret.d_top.d_offset,
        &ret.d_left.d_scale, &ret.d_left.d_offset,
        &ret.d_bottom.d_scale, &ret.d_bottom.d_offset,
        &ret.d_right.d_scale, &ret.d_right.d_offset
    );

    return ret;
}


String PropertyHelper::floatToString(float val)
{
    using namespace std;

    char buff[64];
    snprintf(buff, sizeof(buff), "%g", val);

    return String(buff);

#if 0 // slower
    std::ostringstream iss;
    iss << val;
    return String(iss.str());
#endif
}


String PropertyHelper::uintToString(uint val)
{
    using namespace std;

    char buff[64];
    snprintf(buff, sizeof(buff), "%u", val);

    return String(buff);

#if 0 // slower
    std::ostringstream iss;
    iss << val;
    return String(iss.str());
#endif
}


String PropertyHelper::intToString(int val)
{
    using namespace std;

    char buff[64];
    snprintf(buff, sizeof(buff), "%d", val);

    return String(buff);

#if 0 // slower
    std::ostringstream iss;
    iss << val;
    return String(iss.str());
#endif
}


String PropertyHelper::boolToString(bool val)
{
    if (val)
    {
        return String("True");
    }
    else
    {
        return String("False");
    }

}


String PropertyHelper::sizeToString(const Size& val)
{
    using namespace std;

    char buff[128];
    snprintf(buff, sizeof(buff), "w:%g h:%g", val.d_width, val.d_height);

    return String(buff);

#if 0 // slower
    std::ostringstream iss;
    iss << "w:" << val.d_width << " h:" << val.d_height;
    return String(iss.str());
#endif
}


String PropertyHelper::pointToString(const Point& val)
{
    using namespace std;

    char buff[128];
    snprintf(buff, sizeof(buff), "x:%g y:%g", val.d_x, val.d_y);

    return String(buff);

#if 0 // slower
    std::ostringstream iss;
    iss << "x:" << val.d_x << " y:" << val.d_y;
    return String(iss.str());
#endif
}


String PropertyHelper::rectToString(const Rect& val)
{
    using namespace std;

    char buff[256];
    snprintf(buff, sizeof(buff), "l:%g t:%g r:%g b:%g",
             val.d_left, val.d_top, val.d_right, val.d_bottom);

    return String(buff);

#if 0 // slower
    std::ostringstream iss;
    iss << "l:" << val.d_left << " t:" << val.d_top << " r:" << val.d_right << " b:" << val.d_bottom;
    return String(iss.str());
#endif
}


String PropertyHelper::imageToString(const Image* const val)
{
    if (val)
    {
        return String("set:" + val->getImagesetName() + " image:" + val->getName());
    }

    return String("");
}


String PropertyHelper::udimToString(const UDim& val)
{
    using namespace std;

    char buff[128];
    snprintf(buff, sizeof(buff), "{%g,%g}", val.d_scale, val.d_offset);

    return String(buff);

#if 0
    std::ostringstream iss;
    iss << '{' << val.d_scale << ',' << val.d_offset << '}';
    return String(iss.str());
#endif
}


String PropertyHelper::uvector2ToString(const UVector2& val)
{
    using namespace std;

    char buff[256];
    snprintf(buff, sizeof(buff), "{{%g,%g},{%g,%g}}",
             val.d_x.d_scale, val.d_x.d_offset, val.d_y.d_scale, val.d_y.d_offset);

    return String(buff);

#if 0
    std::ostringstream iss;

    iss << "{{"
    << val.d_x.d_scale << ',' << val.d_x.d_offset << "},{"
    << val.d_y.d_scale << ',' << val.d_y.d_offset << "}}";

    return String(iss.str());
#endif
}


String PropertyHelper::urectToString(const URect& val)
{
    using namespace std;

    char buff[512];
    snprintf(buff, sizeof(buff), "{{%g,%g},{%g,%g},{%g,%g},{%g,%g}}",
             val.d_min.d_x.d_scale, val.d_min.d_x.d_offset,
             val.d_min.d_y.d_scale, val.d_min.d_y.d_offset,
             val.d_max.d_x.d_scale, val.d_max.d_x.d_offset,
             val.d_max.d_y.d_scale, val.d_max.d_y.d_offset);

    return String(buff);

#if 0
    std::ostringstream iss;

    iss << "{{"
    << val.d_min.d_x.d_scale << ',' << val.d_min.d_x.d_offset << "},{"
    << val.d_min.d_y.d_scale << ',' << val.d_min.d_y.d_offset << "},{"
    << val.d_max.d_x.d_scale << ',' << val.d_max.d_x.d_offset << "},{"
    << val.d_max.d_y.d_scale << ',' << val.d_max.d_y.d_offset << "}}";

    return String(iss.str());
#endif
}

String PropertyHelper::uboxToString(const UBox& val)
{
    using namespace std;

    char buff[512];
    snprintf(buff, sizeof(buff), "{top:{%g,%g},left:{%g,%g},bottom:{%g,%g},right:{%g,%g}}",
             val.d_top.d_scale, val.d_top.d_offset,
             val.d_left.d_scale, val.d_left.d_offset,
             val.d_bottom.d_scale, val.d_bottom.d_offset,
             val.d_right.d_scale, val.d_right.d_offset);

    return String(buff);
}

String PropertyHelper::colourToString(const colour& val)
{
    using namespace std;

    char buff[16];
    sprintf(buff, "%.8X", val.getARGB());

    return String(buff);
}


colour PropertyHelper::stringToColour(const String& str)
{
    using namespace std;

    argb_t val = 0xFF000000;
    sscanf(str.c_str(), " %8X", &val);

    return colour(val);

}


String PropertyHelper::colourRectToString(const ColourRect& val)
{
    using namespace std;

    char buff[64];
    sprintf(buff, "tl:%.8X tr:%.8X bl:%.8X br:%.8X", val.d_top_left.getARGB(), val.d_top_right.getARGB(), val.d_bottom_left.getARGB(), val.d_bottom_right.getARGB());

    return String(buff);
}


ColourRect PropertyHelper::stringToColourRect(const String& str)
{
    using namespace std;

    if (str.length() == 8)
    {
        argb_t all = 0xFF000000;
        sscanf(str.c_str(), "%8X", &all);
        return ColourRect(all);
    }

    argb_t topLeft = 0xFF000000, topRight = 0xFF000000, bottomLeft = 0xFF000000, bottomRight = 0xFF000000;
    sscanf(str.c_str(), "tl:%8X tr:%8X bl:%8X br:%8X", &topLeft, &topRight, &bottomLeft, &bottomRight);

    return ColourRect(topLeft, topRight, bottomLeft, bottomRight);
}

//----------------------------------------------------------------------------//
Vector3 PropertyHelper::stringToVector3(const String& str)
{
    using namespace std;

    Vector3 val(0, 0, 0);
    sscanf(str.c_str(), " x:%g y:%g z:%g", &val.d_x, &val.d_y, &val.d_z);

    return val;
}

//----------------------------------------------------------------------------//
String PropertyHelper::vector3ToString(const Vector3& val)
{
    using namespace std;

    char buff[128];
    snprintf(buff, sizeof(buff), "x:%g y:%g z:%g", val.d_x, val.d_y, val.d_z);

    return String(buff);
}

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

} // End of  CEGUI namespace section
