/*
 * Copyright (C) 2004, 2005, 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
 * Copyright (C) 2004, 2005, 2006 Rob Buis <buis@kde.org>
 * Copyright (C) Research In Motion Limited 2010. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "config.h"

#if ENABLE(SVG)
#include "SVGAngle.h"

#include "SVGParserUtilities.h"
#include <wtf/MathExtras.h>
#include <wtf/text/StringConcatenate.h>

namespace WebCore {

SVGAngle::SVGAngle()
    : m_unitType(SVG_ANGLETYPE_UNSPECIFIED)
    , m_valueInSpecifiedUnits(0)
{
}

float SVGAngle::value() const
{
    switch (m_unitType) {
    case SVG_ANGLETYPE_GRAD:
        return grad2deg(m_valueInSpecifiedUnits);
    case SVG_ANGLETYPE_RAD:
        return rad2deg(m_valueInSpecifiedUnits);
    case SVG_ANGLETYPE_UNSPECIFIED:
    case SVG_ANGLETYPE_UNKNOWN:
    case SVG_ANGLETYPE_DEG:
        return m_valueInSpecifiedUnits;
    }

    ASSERT_NOT_REACHED();
    return 0;
}

void SVGAngle::setValue(float value)
{
    switch (m_unitType) {
    case SVG_ANGLETYPE_GRAD:
        m_valueInSpecifiedUnits = deg2grad(value);
        break;
    case SVG_ANGLETYPE_RAD:
        m_valueInSpecifiedUnits = deg2rad(value);
        break;
    case SVG_ANGLETYPE_UNSPECIFIED:
    case SVG_ANGLETYPE_UNKNOWN:
    case SVG_ANGLETYPE_DEG:
        m_valueInSpecifiedUnits = value;
        break;
    }
}

inline SVGAngle::SVGAngleType stringToAngleType(const UChar*& ptr, const UChar* end)
{
    // If there's no unit given, the angle type is unspecified.
    if (ptr == end)
        return SVGAngle::SVG_ANGLETYPE_UNSPECIFIED;

    const UChar firstChar = *ptr;
    
    // If the unit contains only one character, the angle type is unknown.
    ++ptr;
    if (ptr == end)
        return SVGAngle::SVG_ANGLETYPE_UNKNOWN;

    const UChar secondChar = *ptr;
 
    // If the unit contains only two characters, the angle type is unknown.
    ++ptr;
    if (ptr == end)
        return SVGAngle::SVG_ANGLETYPE_UNKNOWN;

    const UChar thirdChar = *ptr;
    if (firstChar == 'd' && secondChar == 'e' && thirdChar == 'g')
        return SVGAngle::SVG_ANGLETYPE_DEG;
    if (firstChar == 'r' && secondChar == 'a' && thirdChar == 'd')
        return SVGAngle::SVG_ANGLETYPE_RAD;

    // If the unit contains three characters, but is not deg or rad, then it's unknown.
    ++ptr;
    if (ptr == end)
        return SVGAngle::SVG_ANGLETYPE_UNKNOWN;

    const UChar fourthChar = *ptr;

    if (firstChar == 'g' && secondChar == 'r' && thirdChar == 'a' && fourthChar == 'd')
        return SVGAngle::SVG_ANGLETYPE_GRAD;

    return SVGAngle::SVG_ANGLETYPE_UNKNOWN;
}

String SVGAngle::valueAsString() const
{
    switch (m_unitType) {
    case SVG_ANGLETYPE_DEG:
        return makeString(String::number(m_valueInSpecifiedUnits), "deg");
    case SVG_ANGLETYPE_RAD:
        return makeString(String::number(m_valueInSpecifiedUnits), "rad");
    case SVG_ANGLETYPE_GRAD:
        return makeString(String::number(m_valueInSpecifiedUnits), "grad");
    case SVG_ANGLETYPE_UNSPECIFIED:
    case SVG_ANGLETYPE_UNKNOWN:
        return makeString(String::number(m_valueInSpecifiedUnits));
    }

    ASSERT_NOT_REACHED();
    return String();
}

void SVGAngle::setValueAsString(const String& value, ExceptionCode& ec)
{
    if (value.isEmpty()) {
        m_unitType = SVG_ANGLETYPE_UNSPECIFIED;
        return;
    }

    float valueInSpecifiedUnits = 0;
    const UChar* ptr = value.characters();
    const UChar* end = ptr + value.length();

    if (!parseNumber(ptr, end, valueInSpecifiedUnits, false)) {
        ec = SYNTAX_ERR;
        return;
    }

    SVGAngleType unitType = stringToAngleType(ptr, end);
    if (unitType == SVG_ANGLETYPE_UNKNOWN) {
        ec = SYNTAX_ERR;
        return;
    }

    m_unitType = unitType;
    m_valueInSpecifiedUnits = valueInSpecifiedUnits;
}

void SVGAngle::newValueSpecifiedUnits(unsigned short unitType, float valueInSpecifiedUnits, ExceptionCode& ec)
{
    if (unitType == SVG_ANGLETYPE_UNKNOWN || unitType > SVG_ANGLETYPE_GRAD) {
        ec = NOT_SUPPORTED_ERR;
        return;
    }

    if (unitType != m_unitType)
        m_unitType = static_cast<SVGAngleType>(unitType);

    m_valueInSpecifiedUnits = valueInSpecifiedUnits;
}

void SVGAngle::convertToSpecifiedUnits(unsigned short unitType, ExceptionCode& ec)
{
    if (unitType == SVG_ANGLETYPE_UNKNOWN || m_unitType == SVG_ANGLETYPE_UNKNOWN || unitType > SVG_ANGLETYPE_GRAD) {
        ec = NOT_SUPPORTED_ERR;
        return;
    }

    if (unitType == m_unitType)
        return;

    switch (m_unitType) {
    case SVG_ANGLETYPE_RAD:
        switch (unitType) {
        case SVG_ANGLETYPE_GRAD:
            m_valueInSpecifiedUnits = rad2grad(m_valueInSpecifiedUnits);
            break;
        case SVG_ANGLETYPE_UNSPECIFIED:
        case SVG_ANGLETYPE_DEG:
            m_valueInSpecifiedUnits = rad2deg(m_valueInSpecifiedUnits);
            break;
        case SVG_ANGLETYPE_RAD:
        case SVG_ANGLETYPE_UNKNOWN:
            ASSERT_NOT_REACHED();
            break;
        }
        break;
    case SVG_ANGLETYPE_GRAD:
        switch (unitType) {
        case SVG_ANGLETYPE_RAD:
            m_valueInSpecifiedUnits = grad2rad(m_valueInSpecifiedUnits);
            break;
        case SVG_ANGLETYPE_UNSPECIFIED:
        case SVG_ANGLETYPE_DEG:
            m_valueInSpecifiedUnits = grad2deg(m_valueInSpecifiedUnits);
            break;
        case SVG_ANGLETYPE_GRAD:
        case SVG_ANGLETYPE_UNKNOWN:
            ASSERT_NOT_REACHED();
            break;
        }
        break;
    case SVG_ANGLETYPE_UNSPECIFIED:
        // Spec: For angles, a unitless value is treated the same as if degrees were specified.
    case SVG_ANGLETYPE_DEG:
        switch (unitType) {
        case SVG_ANGLETYPE_RAD:
            m_valueInSpecifiedUnits = deg2rad(m_valueInSpecifiedUnits);
            break;
        case SVG_ANGLETYPE_GRAD:
            m_valueInSpecifiedUnits = deg2grad(m_valueInSpecifiedUnits);
            break;
        case SVG_ANGLETYPE_UNSPECIFIED:
            break;
        case SVG_ANGLETYPE_DEG:
        case SVG_ANGLETYPE_UNKNOWN:
            ASSERT_NOT_REACHED();
            break;
        }
        break;
    case SVG_ANGLETYPE_UNKNOWN:
        ASSERT_NOT_REACHED();
        break;
    }

    m_unitType = static_cast<SVGAngleType>(unitType);
}

}

#endif // ENABLE(SVG)
