/*
 * Copyright (C) 2012 Adobe Systems Incorporated. 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 THE COPYRIGHT HOLDER “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 THE COPYRIGHT HOLDER 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 "config.h"
#include "BasicShapeFunctions.h"

#include "BasicShapes.h"
#include "CSSBasicShapes.h"
#include "CSSPrimitiveValueMappings.h"
#include "CSSValuePool.h"
#include "Pair.h"
#include "RenderStyle.h"
#include "SVGPathByteStream.h"

namespace WebCore {

static Ref<CSSPrimitiveValue> valueForCenterCoordinate(CSSValuePool& pool, const RenderStyle& style, const BasicShapeCenterCoordinate& center, BoxOrient orientation)
{
    if (center.direction() == BasicShapeCenterCoordinate::TopLeft)
        return pool.createValue(center.length(), style);

    CSSValueID keyword = orientation == BoxOrient::Horizontal ? CSSValueRight : CSSValueBottom;

    return pool.createValue(Pair::create(pool.createIdentifierValue(keyword), pool.createValue(center.length(), style)));
}

static Ref<CSSPrimitiveValue> basicShapeRadiusToCSSValue(const RenderStyle& style, CSSValuePool& pool, const BasicShapeRadius& radius)
{
    switch (radius.type()) {
    case BasicShapeRadius::Value:
        return pool.createValue(radius.value(), style);
    case BasicShapeRadius::ClosestSide:
        return pool.createIdentifierValue(CSSValueClosestSide);
    case BasicShapeRadius::FarthestSide:
        return pool.createIdentifierValue(CSSValueFarthestSide);
    }

    ASSERT_NOT_REACHED();
    return pool.createIdentifierValue(CSSValueClosestSide);
}

Ref<CSSPrimitiveValue> valueForBasicShape(const RenderStyle& style, const BasicShape& basicShape)
{
    auto& cssValuePool = CSSValuePool::singleton();

    RefPtr<CSSBasicShape> basicShapeValue;
    switch (basicShape.type()) {
    case BasicShape::Type::Circle: {
        auto& circle = downcast<BasicShapeCircle>(basicShape);
        auto circleValue = CSSBasicShapeCircle::create();

        circleValue->setCenterX(valueForCenterCoordinate(cssValuePool, style, circle.centerX(), BoxOrient::Horizontal));
        circleValue->setCenterY(valueForCenterCoordinate(cssValuePool, style, circle.centerY(), BoxOrient::Vertical));
        circleValue->setRadius(basicShapeRadiusToCSSValue(style, cssValuePool, circle.radius()));

        basicShapeValue = WTFMove(circleValue);
        break;
    }
    case BasicShape::Type::Ellipse: {
        auto& ellipse = downcast<BasicShapeEllipse>(basicShape);
        auto ellipseValue = CSSBasicShapeEllipse::create();

        ellipseValue->setCenterX(valueForCenterCoordinate(cssValuePool, style, ellipse.centerX(), BoxOrient::Horizontal));
        ellipseValue->setCenterY(valueForCenterCoordinate(cssValuePool, style, ellipse.centerY(), BoxOrient::Vertical));
        ellipseValue->setRadiusX(basicShapeRadiusToCSSValue(style, cssValuePool, ellipse.radiusX()));
        ellipseValue->setRadiusY(basicShapeRadiusToCSSValue(style, cssValuePool, ellipse.radiusY()));

        basicShapeValue = WTFMove(ellipseValue);
        break;
    }
    case BasicShape::Type::Polygon: {
        auto& polygon = downcast<BasicShapePolygon>(basicShape);
        auto polygonValue = CSSBasicShapePolygon::create();

        polygonValue->setWindRule(polygon.windRule());
        const Vector<Length>& values = polygon.values();
        for (unsigned i = 0; i < values.size(); i += 2)
            polygonValue->appendPoint(cssValuePool.createValue(values.at(i), style), cssValuePool.createValue(values.at(i + 1), style));

        basicShapeValue = WTFMove(polygonValue);
        break;
    }
    case BasicShape::Type::Path: {
        auto& pathShape = downcast<BasicShapePath>(basicShape);
        auto pathShapeValue = CSSBasicShapePath::create(pathShape.pathData()->copy());
        pathShapeValue->setWindRule(pathShape.windRule());

        basicShapeValue = WTFMove(pathShapeValue);
        break;
    }
    case BasicShape::Type::Inset: {
        auto& inset = downcast<BasicShapeInset>(basicShape);
        auto insetValue = CSSBasicShapeInset::create();

        insetValue->setTop(cssValuePool.createValue(inset.top(), style));
        insetValue->setRight(cssValuePool.createValue(inset.right(), style));
        insetValue->setBottom(cssValuePool.createValue(inset.bottom(), style));
        insetValue->setLeft(cssValuePool.createValue(inset.left(), style));

        insetValue->setTopLeftRadius(cssValuePool.createValue(inset.topLeftRadius(), style));
        insetValue->setTopRightRadius(cssValuePool.createValue(inset.topRightRadius(), style));
        insetValue->setBottomRightRadius(cssValuePool.createValue(inset.bottomRightRadius(), style));
        insetValue->setBottomLeftRadius(cssValuePool.createValue(inset.bottomLeftRadius(), style));

        basicShapeValue = WTFMove(insetValue);
        break;
    }
    }

    return cssValuePool.createValue(basicShapeValue.releaseNonNull());
}

static Length convertToLength(const CSSToLengthConversionData& conversionData, const CSSPrimitiveValue* value)
{
    return value->convertToLength<FixedIntegerConversion | FixedFloatConversion | PercentConversion | CalculatedConversion>(conversionData);
}

static LengthSize convertToLengthSize(const CSSToLengthConversionData& conversionData, const CSSPrimitiveValue* value)
{
    if (!value)
        return { { 0, Fixed }, { 0, Fixed } };

    auto& pair = *value->pairValue();
    return { convertToLength(conversionData, pair.first()), convertToLength(conversionData, pair.second()) };
}

static BasicShapeCenterCoordinate convertToCenterCoordinate(const CSSToLengthConversionData& conversionData, CSSPrimitiveValue* value)
{
    CSSValueID keyword = CSSValueTop;
    Length offset { 0, Fixed };
    if (!value)
        keyword = CSSValueCenter;
    else if (value->isValueID())
        keyword = value->valueID();
    else if (Pair* pair = value->pairValue()) {
        keyword = pair->first()->valueID();
        offset = convertToLength(conversionData, pair->second());
    } else
        offset = convertToLength(conversionData, value);

    BasicShapeCenterCoordinate::Direction direction;
    switch (keyword) {
    case CSSValueTop:
    case CSSValueLeft:
        direction = BasicShapeCenterCoordinate::TopLeft;
        break;
    case CSSValueRight:
    case CSSValueBottom:
        direction = BasicShapeCenterCoordinate::BottomRight;
        break;
    case CSSValueCenter:
        direction = BasicShapeCenterCoordinate::TopLeft;
        offset = Length(50, Percent);
        break;
    default:
        ASSERT_NOT_REACHED();
        direction = BasicShapeCenterCoordinate::TopLeft;
        break;
    }

    return BasicShapeCenterCoordinate(direction, offset);
}

static BasicShapeRadius cssValueToBasicShapeRadius(const CSSToLengthConversionData& conversionData, CSSPrimitiveValue* radius)
{
    if (!radius)
        return BasicShapeRadius(BasicShapeRadius::ClosestSide);

    if (radius->isValueID()) {
        switch (radius->valueID()) {
        case CSSValueClosestSide:
            return BasicShapeRadius(BasicShapeRadius::ClosestSide);
        case CSSValueFarthestSide:
            return BasicShapeRadius(BasicShapeRadius::FarthestSide);
        default:
            ASSERT_NOT_REACHED();
            break;
        }
    }

    return BasicShapeRadius(convertToLength(conversionData, radius));
}

Ref<BasicShape> basicShapeForValue(const CSSToLengthConversionData& conversionData, const CSSBasicShape& basicShapeValue)
{
    RefPtr<BasicShape> basicShape;

    switch (basicShapeValue.type()) {
    case CSSBasicShape::CSSBasicShapeCircleType: {
        auto& circleValue = downcast<CSSBasicShapeCircle>(basicShapeValue);
        auto circle = BasicShapeCircle::create();

        circle->setCenterX(convertToCenterCoordinate(conversionData, circleValue.centerX()));
        circle->setCenterY(convertToCenterCoordinate(conversionData, circleValue.centerY()));
        circle->setRadius(cssValueToBasicShapeRadius(conversionData, circleValue.radius()));

        basicShape = WTFMove(circle);
        break;
    }
    case CSSBasicShape::CSSBasicShapeEllipseType: {
        auto& ellipseValue = downcast<CSSBasicShapeEllipse>(basicShapeValue);
        auto ellipse = BasicShapeEllipse::create();

        ellipse->setCenterX(convertToCenterCoordinate(conversionData, ellipseValue.centerX()));
        ellipse->setCenterY(convertToCenterCoordinate(conversionData, ellipseValue.centerY()));

        ellipse->setRadiusX(cssValueToBasicShapeRadius(conversionData, ellipseValue.radiusX()));
        ellipse->setRadiusY(cssValueToBasicShapeRadius(conversionData, ellipseValue.radiusY()));

        basicShape = WTFMove(ellipse);
        break;
    }
    case CSSBasicShape::CSSBasicShapePolygonType: {
        auto& polygonValue = downcast<CSSBasicShapePolygon>(basicShapeValue);
        auto polygon = BasicShapePolygon::create();

        polygon->setWindRule(polygonValue.windRule());
        auto& values = polygonValue.values();
        for (unsigned i = 0; i < values.size(); i += 2)
            polygon->appendPoint(convertToLength(conversionData, values[i].ptr()), convertToLength(conversionData, values[i + 1].ptr()));

        basicShape = WTFMove(polygon);
        break;
    }
    case CSSBasicShape::CSSBasicShapeInsetType: {
        auto& rectValue = downcast<CSSBasicShapeInset>(basicShapeValue);
        auto rect = BasicShapeInset::create();

        rect->setTop(convertToLength(conversionData, rectValue.top()));
        rect->setRight(convertToLength(conversionData, rectValue.right()));
        rect->setBottom(convertToLength(conversionData, rectValue.bottom()));
        rect->setLeft(convertToLength(conversionData, rectValue.left()));

        rect->setTopLeftRadius(convertToLengthSize(conversionData, rectValue.topLeftRadius()));
        rect->setTopRightRadius(convertToLengthSize(conversionData, rectValue.topRightRadius()));
        rect->setBottomRightRadius(convertToLengthSize(conversionData, rectValue.bottomRightRadius()));
        rect->setBottomLeftRadius(convertToLengthSize(conversionData, rectValue.bottomLeftRadius()));

        basicShape = WTFMove(rect);
        break;
    }
    case CSSBasicShape::CSSBasicShapePathType: {
        auto& pathValue = downcast<CSSBasicShapePath>(basicShapeValue);
        auto path = BasicShapePath::create(pathValue.pathData().copy());
        path->setWindRule(pathValue.windRule());

        basicShape = WTFMove(path);
        break;
    }
    }

    return basicShape.releaseNonNull();
}

float floatValueForCenterCoordinate(const BasicShapeCenterCoordinate& center, float boxDimension)
{
    float offset = floatValueForLength(center.length(), boxDimension);
    if (center.direction() == BasicShapeCenterCoordinate::TopLeft)
        return offset;
    return boxDimension - offset;
}

}
