/*
 * Copyright (C) 2016 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 "config.h"
#include "Path.h"

#if USE(DIRECT2D)

#include "AffineTransform.h"
#include "COMPtr.h"
#include "FloatRect.h"
#include "GraphicsContext.h"
#include "IntRect.h"
#include "NotImplemented.h"
#include "StrokeStyleApplier.h"
#include <d2d1.h>
#include <wtf/MathExtras.h>
#include <wtf/RetainPtr.h>
#include <wtf/text/WTFString.h>

namespace WebCore {

static inline ID2D1RenderTarget* scratchRenderTarget()
{
    static COMPtr<ID2D1RenderTarget> renderTarget = adoptCOM(GraphicsContext::defaultRenderTarget());
    return renderTarget.get();
}

Path Path::polygonPathFromPoints(const Vector<FloatPoint>& points)
{
    Path path;
    if (points.size() < 2)
        return path;

    Vector<D2D1_POINT_2F, 32> d2dPoints;
    d2dPoints.reserveInitialCapacity(points.size() - 1);
    for (auto point : points)
        d2dPoints.uncheckedAppend(point);

    path.moveTo(points.first());

    ASSERT(path.activePath());

    path.activePath()->AddLines(d2dPoints.data(), d2dPoints.size());
    path.closeSubpath();

    return path;
}

Path::Path() = default;

Path::~Path() = default;

PlatformPathPtr Path::ensurePlatformPath()
{
    if (!m_path) {
        HRESULT hr = GraphicsContext::systemFactory()->CreateGeometryGroup(D2D1_FILL_MODE_WINDING, nullptr, 0, &m_path);
        ASSERT(SUCCEEDED(hr));
        if (FAILED(hr))
            return nullptr;
    }

    return m_path.get();
}

void Path::appendGeometry(ID2D1Geometry* geometry)
{
    unsigned geometryCount = m_path ? m_path->GetSourceGeometryCount() : 0;
    Vector<ID2D1Geometry*> geometries(geometryCount, nullptr);

    // Note: 'GetSourceGeometries' returns geometries that have a +1 ref count.
    // so they must be released before we return.
    if (geometryCount)
        m_path->GetSourceGeometries(geometries.data(), geometryCount);

    geometry->AddRef();
    geometries.append(geometry);

    auto fillMode = m_path ? m_path->GetFillMode() : D2D1_FILL_MODE_WINDING;

    COMPtr<ID2D1GeometryGroup> protectedPath = m_path;
    m_path = nullptr;

    HRESULT hr = GraphicsContext::systemFactory()->CreateGeometryGroup(fillMode, geometries.data(), geometries.size(), &m_path);
    RELEASE_ASSERT(SUCCEEDED(hr));

    for (auto entry : geometries)
        entry->Release();
}

void Path::createGeometryWithFillMode(WindRule webkitFillMode, COMPtr<ID2D1GeometryGroup>& path) const
{
    RELEASE_ASSERT(m_path);

    auto fillMode = (webkitFillMode == RULE_EVENODD) ? D2D1_FILL_MODE_ALTERNATE : D2D1_FILL_MODE_WINDING;

    if (fillMode == m_path->GetFillMode()) {
        path = m_path;
        return;
    }

    unsigned geometryCount = m_path->GetSourceGeometryCount();

    Vector<ID2D1Geometry*> geometries(geometryCount, nullptr);
    ASSERT(geometryCount);

    // Note: 'GetSourceGeometries' returns geometries that have a +1 ref count.
    // so they must be released before we return.
    m_path->GetSourceGeometries(geometries.data(), geometryCount);

    HRESULT hr = GraphicsContext::systemFactory()->CreateGeometryGroup(fillMode, geometries.data(), geometries.size(), &path);
    RELEASE_ASSERT(SUCCEEDED(hr));

    for (auto entry : geometries)
        entry->Release();
}

Path::Path(const Path& other)
{
    if (other.platformPath() && other.activePath()) {
        auto otherPath = other.platformPath();

        unsigned geometryCount = otherPath->GetSourceGeometryCount();

        Vector<ID2D1Geometry*> geometries(geometryCount, nullptr);
        ASSERT(geometryCount);

        // Note: 'GetSourceGeometries' returns geometries that have a +1 ref count.
        // so they must be released before we return.
        otherPath->GetSourceGeometries(geometries.data(), geometryCount);

        HRESULT hr = GraphicsContext::systemFactory()->CreateGeometryGroup(other.m_path->GetFillMode(), geometries.data(), geometryCount, &m_path);
        RELEASE_ASSERT(SUCCEEDED(hr));

        for (auto entry : geometries)
            entry->Release();
    }
}
    
Path::Path(Path&& other)
{
    m_path = other.m_path;
    m_activePath = other.m_activePath;
    m_activePathGeometry = other.m_activePathGeometry;
    other.m_path = nullptr;
    other.m_activePath = nullptr;
    other.m_activePathGeometry = nullptr;
}

Path& Path::operator=(const Path& other)
{
    m_path = other.m_path;
    m_activePath = other.m_activePath;
    m_activePathGeometry = other.m_activePathGeometry;
    return *this;
}

Path& Path::operator=(Path&& other)
{
    if (this == &other)
        return *this;
    m_path = other.m_path;
    m_activePath = other.m_activePath;
    m_activePathGeometry = other.m_activePathGeometry;
    other.m_path = nullptr;
    other.m_activePath = nullptr;
    other.m_activePathGeometry = nullptr;
    return *this;
}

HRESULT Path::initializePathState()
{
    m_path = nullptr;
    m_activePath = nullptr;
    m_activePathGeometry = nullptr;

    GraphicsContext::systemFactory()->CreatePathGeometry(&m_activePathGeometry);

    Vector<ID2D1Geometry*> geometries;
    geometries.append(m_activePathGeometry.get());

    HRESULT hr = GraphicsContext::systemFactory()->CreateGeometryGroup(D2D1_FILL_MODE_WINDING, geometries.data(), geometries.size(), &m_path);
    if (FAILED(hr))
        return hr;

    return m_activePathGeometry->Open(&m_activePath);
}

void Path::drawDidComplete() const
{
    FloatPoint currentPoint = this->currentPoint();

    // To maintain proper semantics with CG, we need to clear our Direct2D
    // path objects when a draw has finished.
    HRESULT hr = const_cast<Path*>(this)->initializePathState();

    if (!SUCCEEDED(hr))
        return;

    m_activePath->SetFillMode(D2D1_FILL_MODE_WINDING);

    m_activePath->BeginFigure(currentPoint, D2D1_FIGURE_BEGIN_FILLED);
}

bool Path::contains(const FloatPoint& point, WindRule rule) const
{
    if (isNull())
        return false;

    if (!fastBoundingRect().contains(point))
        return false;

    BOOL contains;
    if (!SUCCEEDED(m_path->FillContainsPoint(D2D1::Point2F(point.x(), point.y()), nullptr, &contains)))
        return false;

    return contains;
}

bool Path::strokeContains(StrokeStyleApplier* applier, const FloatPoint& point) const
{
    if (isNull())
        return false;

    ASSERT(applier);

    GraphicsContext scratchContext(scratchRenderTarget());
    applier->strokeStyle(&scratchContext);

    BOOL containsPoint = false;
    HRESULT hr = m_path->StrokeContainsPoint(point, scratchContext.strokeThickness(), scratchContext.platformStrokeStyle(), nullptr, 1.0f, &containsPoint);
    if (!SUCCEEDED(hr))
        return false;

    return containsPoint;
}

void Path::translate(const FloatSize& size)
{
    transform(AffineTransform(1, 0, 0, 1, size.width(), size.height()));
}

void Path::transform(const AffineTransform& transform)
{
    if (transform.isIdentity() || isEmpty())
        return;

    bool pathIsActive = false;
    if (m_activePath) {
        m_activePath->Close();
        m_activePath = nullptr;
        m_activePathGeometry = nullptr;
        pathIsActive = true;
    }

    const D2D1_MATRIX_3X2_F& d2dTransform = static_cast<const D2D1_MATRIX_3X2_F>(transform);
    COMPtr<ID2D1TransformedGeometry> transformedPath;
    if (!SUCCEEDED(GraphicsContext::systemFactory()->CreateTransformedGeometry(m_path.get(), d2dTransform, &transformedPath)))
        return;

    Vector<ID2D1Geometry*> geometries;
    geometries.append(transformedPath.get());

    if (pathIsActive) {
        GraphicsContext::systemFactory()->CreatePathGeometry(&m_activePathGeometry);
        m_activePathGeometry->Open(&m_activePath);
        geometries.append(m_activePathGeometry.get());
    }

    auto fillMode = m_path->GetFillMode();

    m_path = nullptr;

    HRESULT hr = GraphicsContext::systemFactory()->CreateGeometryGroup(fillMode, geometries.data(), geometries.size(), &m_path);
    RELEASE_ASSERT(SUCCEEDED(hr));
}

FloatRect Path::boundingRect() const
{
    if (isNull())
        return FloatRect();

    D2D1_RECT_F bounds = { };
    if (!SUCCEEDED(m_path->GetBounds(nullptr, &bounds)))
        return FloatRect();

    return bounds;
}

FloatRect Path::fastBoundingRect() const
{
    if (isNull())
        return FloatRect();

    D2D1_RECT_F bounds = { };
    if (!SUCCEEDED(m_path->GetBounds(nullptr, &bounds)))
        return FloatRect();

    return bounds;
}

FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier) const
{
    if (isNull())
        return FloatRect();

    if (!applier)
        return boundingRect();

    UNUSED_PARAM(applier);
    notImplemented();

    // Just return regular bounding rect for now.
    return boundingRect();
}

void Path::moveTo(const FloatPoint& point)
{
    if (!m_activePath) {
        GraphicsContext::systemFactory()->CreatePathGeometry(&m_activePathGeometry);

        appendGeometry(m_activePathGeometry.get());

        if (!SUCCEEDED(m_activePathGeometry->Open(&m_activePath)))
            return;

        m_activePath->SetFillMode(D2D1_FILL_MODE_WINDING);
    }

    m_activePath->BeginFigure(point, D2D1_FIGURE_BEGIN_FILLED);
}

void Path::addLineTo(const FloatPoint& point)
{
    ASSERT(m_activePath.get());

    m_activePath->AddLine(point);
}

void Path::addQuadCurveTo(const FloatPoint& cp, const FloatPoint& p)
{
    ASSERT(m_activePath.get());

    m_activePath->AddQuadraticBezier(D2D1::QuadraticBezierSegment(cp, p));
}

void Path::addBezierCurveTo(const FloatPoint& cp1, const FloatPoint& cp2, const FloatPoint& p)
{
    ASSERT(m_activePath.get());

    FloatPoint beforePoint = currentPoint();

    m_activePath->AddBezier(D2D1::BezierSegment(cp1, cp2, p));
}

void Path::addArcTo(const FloatPoint& p1, const FloatPoint& p2, float radius)
{
    UNUSED_PARAM(p1);
    UNUSED_PARAM(p2);
    UNUSED_PARAM(radius);
    notImplemented();
}

static bool equalRadiusWidths(const FloatSize& topLeftRadius, const FloatSize& topRightRadius, const FloatSize& bottomLeftRadius, const FloatSize& bottomRightRadius)
{
    return topLeftRadius.width() == topRightRadius.width()
        && topRightRadius.width() == bottomLeftRadius.width()
        && bottomLeftRadius.width() == bottomRightRadius.width();
}

static bool equalRadiusHeights(const FloatSize& topLeftRadius, const FloatSize& topRightRadius, const FloatSize& bottomLeftRadius, const FloatSize& bottomRightRadius)
{
    return topLeftRadius.height() == bottomLeftRadius.height()
        && bottomLeftRadius.height() == topRightRadius.height()
        && topRightRadius.height() == bottomRightRadius.height();
}

void Path::platformAddPathForRoundedRect(const FloatRect& rect, const FloatSize& topLeftRadius, const FloatSize& topRightRadius, const FloatSize& bottomLeftRadius, const FloatSize& bottomRightRadius)
{
    bool equalWidths = equalRadiusWidths(topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius);
    bool equalHeights = equalRadiusHeights(topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius);

    if (equalWidths && equalHeights) {
        // Ensure that CG can render the rounded rect.
        float radiusWidth = topLeftRadius.width();
        float radiusHeight = topLeftRadius.height();
        auto rectToDraw = D2D1::RectF(rect.x(), rect.y(), rect.maxX(), rect.maxY());

        COMPtr<ID2D1RoundedRectangleGeometry> roundRect;
        HRESULT hr = GraphicsContext::systemFactory()->CreateRoundedRectangleGeometry(D2D1::RoundedRect(rectToDraw, radiusWidth, radiusHeight), &roundRect);
        RELEASE_ASSERT(SUCCEEDED(hr));
        appendGeometry(roundRect.get());
        return;
    }

    addBeziersForRoundedRect(rect, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius);
}

void Path::closeSubpath()
{
    if (isNull())
        return;

    ASSERT(m_activePath.get());
    m_activePath->EndFigure(D2D1_FIGURE_END_OPEN);
}

static FloatPoint arcStart(const FloatPoint& center, float radius, float startAngle)
{
    FloatPoint startingPoint = center;
    float startX = radius * std::cos(startAngle);
    float startY = radius * std::sin(startAngle);
    startingPoint.move(startX, startY);
    return startingPoint;
}

static void drawArcSection(ID2D1GeometrySink* sink, const FloatPoint& center, float radius, float startAngle, float endAngle, bool clockwise)
{
    // Direct2D wants us to specify the end point of the arc, not the center. It will be drawn from
    // whatever the current point in the 'm_activePath' is.
    FloatPoint p = center;
    float endX = radius * std::cos(endAngle);
    float endY = radius * std::sin(endAngle);
    p.move(endX, endY);

    float arcDeg = rad2deg(endAngle - startAngle);
    D2D1_SWEEP_DIRECTION direction = clockwise ? D2D1_SWEEP_DIRECTION_CLOCKWISE : D2D1_SWEEP_DIRECTION_COUNTER_CLOCKWISE;
    sink->AddArc(D2D1::ArcSegment(p, D2D1::SizeF(radius, radius), arcDeg, direction, D2D1_ARC_SIZE_SMALL));
}

void Path::addArc(const FloatPoint& center, float radius, float startAngle, float endAngle, bool clockwise)
{
    auto arcStartPoint = arcStart(center, radius, startAngle);
    if (!m_activePath)
        moveTo(arcStartPoint);
    else if (!areEssentiallyEqual(currentPoint(), arcStartPoint)) {
        // If the arc defined by the center and radius does not intersect the current position,
        // we need to draw a line from the current position to the starting point of the arc.
        addLineTo(arcStartPoint);
    }

    // Direct2D has problems drawing large arcs. It gets confused if drawing a complete (or
    // nearly complete) circle in the counter-clockwise direction. So, draw any arcs larger
    // than 180 degrees in two pieces.
    float fullSweep = endAngle - startAngle;
    float negate = fullSweep < 0 ? -1.0f : 1.0f;
    float maxSweep = negate * std::min(std::abs(fullSweep), piFloat);
    float firstArcEnd = startAngle + maxSweep;
    drawArcSection(m_activePath.get(), center, radius, startAngle, firstArcEnd, clockwise);

    if (WTF::areEssentiallyEqual(firstArcEnd, endAngle))
        return;

    drawArcSection(m_activePath.get(), center, radius, firstArcEnd, endAngle, clockwise);
}

void Path::addRect(const FloatRect& r)
{
    COMPtr<ID2D1RectangleGeometry> rectangle;
    HRESULT hr = GraphicsContext::systemFactory()->CreateRectangleGeometry(r, &rectangle);
    RELEASE_ASSERT(SUCCEEDED(hr));
    appendGeometry(rectangle.get());
}

void Path::addEllipse(FloatPoint p, float radiusX, float radiusY, float rotation, float startAngle, float endAngle, bool anticlockwise)
{
    AffineTransform transform;
    transform.translate(p.x(), p.y()).rotate(rad2deg(rotation)).scale(radiusX, radiusY);

    notImplemented();
}

void Path::addEllipse(const FloatRect& r)
{
    COMPtr<ID2D1EllipseGeometry> ellipse;
    HRESULT hr = GraphicsContext::systemFactory()->CreateEllipseGeometry(D2D1::Ellipse(r.center(), r.width(), r.height()), &ellipse);
    RELEASE_ASSERT(SUCCEEDED(hr));
    appendGeometry(ellipse.get());
}

void Path::addPath(const Path& path, const AffineTransform& transform)
{
    if (!path.platformPath())
        return;

    if (!transform.isInvertible())
        return;

    notImplemented();
}


void Path::clear()
{
    if (isNull())
        return;

    m_path = nullptr;
    m_activePath = nullptr;
    m_activePathGeometry = nullptr;
}

bool Path::isEmpty() const
{
    if (isNull())
        return true;

    if (!m_path->GetSourceGeometryCount())
        return true;

    return false;
}

bool Path::hasCurrentPoint() const
{
    return !isEmpty();
}
    
FloatPoint Path::currentPoint() const 
{
    if (isNull())
        return FloatPoint();

    float length = 0;
    HRESULT hr = m_path->ComputeLength(nullptr, &length);
    if (!SUCCEEDED(hr))
        return FloatPoint();

    D2D1_POINT_2F point = { };
    D2D1_POINT_2F tangent = { };
    hr = m_path->ComputePointAtLength(length, nullptr, &point, &tangent);
    if (!SUCCEEDED(hr))
        return FloatPoint();

    return point;
}

float Path::length() const
{
    float length = 0;
    HRESULT hr = m_path->ComputeLength(nullptr, &length);
    if (!SUCCEEDED(hr))
        return 0;

    return length;
}

void Path::apply(const PathApplierFunction& function) const
{
    if (isNull())
        return;

    notImplemented();
}

}

#endif // USE(DIRECT2D)
