/*
 * Copyright (C) 2008 Apple Inc. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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 "sky/engine/core/css/CSSMatrix.h"

#include "gen/sky/core/CSSPropertyNames.h"
#include "gen/sky/core/CSSValueKeywords.h"
#include "sky/engine/bindings/exception_state.h"
#include "sky/engine/core/css/CSSToLengthConversionData.h"
#include "sky/engine/core/css/StylePropertySet.h"
#include "sky/engine/core/css/parser/BisonCSSParser.h"
#include "sky/engine/core/css/resolver/TransformBuilder.h"
#include "sky/engine/core/dom/ExceptionCode.h"
#include "sky/engine/core/rendering/style/RenderStyle.h"
#include "sky/engine/core/rendering/style/StyleInheritedData.h"
#include "sky/engine/wtf/MathExtras.h"

namespace blink {

CSSMatrix::CSSMatrix(const TransformationMatrix& m)
    : m_matrix(m)
{
}

CSSMatrix::CSSMatrix(const String& s, ExceptionState& exceptionState)
{
    setMatrixValue(s, exceptionState);
}

void CSSMatrix::setMatrixValue(const String& string, ExceptionState& exceptionState)
{
    if (string.isEmpty())
        return;

    // FIXME: crbug.com/154722 - should this continue to use legacy style parsing?
    RefPtr<MutableStylePropertySet> styleDeclaration = MutableStylePropertySet::create();
    if (BisonCSSParser::parseValue(styleDeclaration.get(), CSSPropertyWebkitTransform, string, HTMLStandardMode, 0)) {
        // Convert to TransformOperations. This can fail if a property
        // requires style (i.e., param uses 'ems' or 'exs')
        RefPtr<CSSValue> value = styleDeclaration->getPropertyCSSValue(CSSPropertyWebkitTransform);

        // Check for a "none" or empty transform. In these cases we can use the default identity matrix.
        if (!value || (value->isPrimitiveValue() && (toCSSPrimitiveValue(value.get()))->getValueID() == CSSValueNone))
            return;

        DEFINE_STATIC_REF(RenderStyle, defaultStyle, RenderStyle::createDefaultStyle());
        TransformOperations operations;
        if (!TransformBuilder::createTransformOperations(value.get(), CSSToLengthConversionData(defaultStyle, 0), operations)) {
            exceptionState.ThrowDOMException(SyntaxError, "Failed to interpret '" + string + "' as a transformation operation.");
            return;
        }

        // Convert transform operations to a TransformationMatrix. This can fail
        // if a param has a percentage ('%')
        if (operations.dependsOnBoxSize())
            exceptionState.ThrowDOMException(SyntaxError, "The transformation depends on the box size, which is not supported.");
        TransformationMatrix t;
        operations.apply(FloatSize(0, 0), t);

        // set the matrix
        m_matrix = t;
    } else { // There is something there but parsing failed.
        exceptionState.ThrowDOMException(SyntaxError, "Failed to parse '" + string + "'.");
    }
}

// Perform a concatenation of the matrices (this * secondMatrix)
PassRefPtr<CSSMatrix> CSSMatrix::multiply(CSSMatrix* secondMatrix) const
{
    if (!secondMatrix)
        return nullptr;

    return CSSMatrix::create(TransformationMatrix(m_matrix).multiply(secondMatrix->m_matrix));
}

PassRefPtr<CSSMatrix> CSSMatrix::inverse(ExceptionState& exceptionState) const
{
    if (!m_matrix.isInvertible()) {
        exceptionState.ThrowDOMException(NotSupportedError, "The matrix is not invertable.");
        return nullptr;
    }

    return CSSMatrix::create(m_matrix.inverse());
}

PassRefPtr<CSSMatrix> CSSMatrix::translate(double x, double y, double z) const
{
    if (std::isnan(x))
        x = 0;
    if (std::isnan(y))
        y = 0;
    if (std::isnan(z))
        z = 0;
    return CSSMatrix::create(TransformationMatrix(m_matrix).translate3d(x, y, z));
}

PassRefPtr<CSSMatrix> CSSMatrix::scale(double scaleX, double scaleY, double scaleZ) const
{
    if (std::isnan(scaleX))
        scaleX = 1;
    if (std::isnan(scaleY))
        scaleY = scaleX;
    if (std::isnan(scaleZ))
        scaleZ = 1;
    return CSSMatrix::create(TransformationMatrix(m_matrix).scale3d(scaleX, scaleY, scaleZ));
}

PassRefPtr<CSSMatrix> CSSMatrix::rotate(double rotX, double rotY, double rotZ) const
{
    if (std::isnan(rotX))
        rotX = 0;

    if (std::isnan(rotY) && std::isnan(rotZ)) {
        rotZ = rotX;
        rotX = 0;
        rotY = 0;
    }

    if (std::isnan(rotY))
        rotY = 0;
    if (std::isnan(rotZ))
        rotZ = 0;
    return CSSMatrix::create(TransformationMatrix(m_matrix).rotate3d(rotX, rotY, rotZ));
}

PassRefPtr<CSSMatrix> CSSMatrix::rotateAxisAngle(double x, double y, double z, double angle) const
{
    if (std::isnan(x))
        x = 0;
    if (std::isnan(y))
        y = 0;
    if (std::isnan(z))
        z = 0;
    if (std::isnan(angle))
        angle = 0;
    if (!x && !y && !z)
        z = 1;
    return CSSMatrix::create(TransformationMatrix(m_matrix).rotate3d(x, y, z, angle));
}

PassRefPtr<CSSMatrix> CSSMatrix::skewX(double angle) const
{
    if (std::isnan(angle))
        angle = 0;
    return CSSMatrix::create(TransformationMatrix(m_matrix).skewX(angle));
}

PassRefPtr<CSSMatrix> CSSMatrix::skewY(double angle) const
{
    if (std::isnan(angle))
        angle = 0;
    return CSSMatrix::create(TransformationMatrix(m_matrix).skewY(angle));
}

String CSSMatrix::toString() const
{
    // FIXME - Need to ensure valid CSS floating point values (https://bugs.webkit.org/show_bug.cgi?id=20674)
    if (m_matrix.isAffine())
        return String::format("matrix(%f, %f, %f, %f, %f, %f)", m_matrix.a(), m_matrix.b(), m_matrix.c(), m_matrix.d(), m_matrix.e(), m_matrix.f());
    return String::format("matrix3d(%f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f)",
    m_matrix.m11(), m_matrix.m12(), m_matrix.m13(), m_matrix.m14(),
    m_matrix.m21(), m_matrix.m22(), m_matrix.m23(), m_matrix.m24(),
    m_matrix.m31(), m_matrix.m32(), m_matrix.m33(), m_matrix.m34(),
    m_matrix.m41(), m_matrix.m42(), m_matrix.m43(), m_matrix.m44());
}

} // namespace blink
