/*
 * Copyright (C) 2016-2019 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 "PlatformContextDirect2D.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.m_activePath);

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

    return path;
}

Path::Path() = default;

Path::~Path()
{
    clearGeometries();
}

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;
        ASSERT(refCount(m_path.get()) == 1);
    }

    return m_path.get();
}

void Path::clearGeometries()
{
    // Manually clean these up so that we can use this vector with Direct2D APIs.
    for (auto* geometry : m_geometries)
        geometry->Release();
    m_geometries.clear();
}

void Path::appendGeometry(ID2D1Geometry* geometry)
{
#if !ASSERT_DISABLED
    unsigned before = refCount(geometry);
#endif

    unsigned geometryCount = m_path ? m_path->GetSourceGeometryCount() : 0;

    RELEASE_ASSERT(m_geometries.size() == geometryCount);

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

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

    m_path = nullptr;

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

    ASSERT(refCount(geometry) == before + 1);
}

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

    auto fillMode = (webkitFillMode == WindRule::EvenOdd) ? D2D1_FILL_MODE_ALTERNATE : D2D1_FILL_MODE_WINDING;

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

    unsigned geometryCount = m_path->GetSourceGeometryCount();

    ASSERT(m_geometries.size() == geometryCount);

    HRESULT hr = GraphicsContext::systemFactory()->CreateGeometryGroup(fillMode, const_cast<ID2D1Geometry**>(m_geometries.data()), m_geometries.size(), &path);
    RELEASE_ASSERT(SUCCEEDED(hr));
    ASSERT(refCount(path.get()) == 1);
}

Path::Path(const Path& other)
{
#if !ASSERT_DISABLED
    unsigned pathCount = refCount(other.m_path.get());
    unsigned activePathCount = refCount(other.m_activePath.get());
#endif
    m_path = other.m_path;
    m_activePath = other.m_activePath;
    m_geometries = other.m_geometries;
    for (auto* geometry : m_geometries)
        geometry->AddRef();

    ASSERT(!m_path || refCount(m_path.get()) == pathCount + 1);
    ASSERT(!m_activePath || refCount(m_activePath.get()) == activePathCount + 1);
}
    
Path::Path(Path&& other)
{
#if !ASSERT_DISABLED
    unsigned pathCount = refCount(other.m_path.get());
    unsigned activePathCount = refCount(other.m_activePath.get());
#endif
    m_path = WTFMove(other.m_path);
    m_activePath = WTFMove(other.m_activePath);
    m_geometries = WTFMove(other.m_geometries);

    ASSERT(refCount(m_path.get()) == pathCount);
    ASSERT(refCount(m_activePath.get()) == activePathCount);
}

Path& Path::operator=(const Path& other)
{
    if (this == &other)
        return *this;
#if !ASSERT_DISABLED
    unsigned pathCount = refCount(other.m_path.get());
    unsigned activePathCount = refCount(other.m_activePath.get());
#endif
    m_path = other.m_path;
    m_activePath = other.m_activePath;
    m_geometries = other.m_geometries;
    for (auto* geometry : m_geometries)
        geometry->AddRef();

    ASSERT(!m_path || refCount(m_path.get()) == pathCount + 1);
    ASSERT(!m_activePath || refCount(m_activePath.get()) == activePathCount + 1);

    return *this;
}

Path& Path::operator=(Path&& other)
{
    if (this == &other)
        return *this;

#if !ASSERT_DISABLED
    unsigned pathCount = refCount(other.m_path.get());
    unsigned activePathCount = refCount(other.m_activePath.get());
#endif
    m_path = WTFMove(other.m_path);
    m_activePath = WTFMove(other.m_activePath);
    m_geometries = WTFMove(other.m_geometries);

    ASSERT(refCount(m_path.get()) == pathCount);
    ASSERT(refCount(m_activePath.get()) == activePathCount);

    return *this;
}

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(point, nullptr, &contains)))
        return false;

    return contains;
}

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

    ASSERT(applier);

    PlatformContextDirect2D scratchContextD2D(scratchRenderTarget());
    GraphicsContext scratchContext(&scratchContextD2D, GraphicsContext::BitmapRenderingContextType::GPUMemory);
    applier->strokeStyle(&scratchContext);

#if !ASSERT_DISABLED
    unsigned before = refCount(m_path.get());
#endif

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

    ASSERT(refCount(m_path.get()) == before);
    return containsPoint;
}

void Path::closeAnyOpenGeometries(unsigned figureEndStyle) const
{
    if (m_figureIsOpened) {
        ASSERT(m_activePath);

        auto endStyle = static_cast<D2D1_FIGURE_END>(figureEndStyle);
        m_activePath->EndFigure(endStyle);
        m_figureIsOpened = false;

        HRESULT hr = m_activePath->Close();
        ASSERT(SUCCEEDED(hr));
    }

    m_activePath = nullptr;
}

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;

    if (m_activePath)
        closeAnyOpenGeometries(D2D1_FIGURE_END_OPEN);

#if !ASSERT_DISABLED
    unsigned before = refCount(m_path.get());
#endif

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

    ASSERT(refCount(m_path.get()) == before);
    ASSERT(refCount(transformedPath.get()) == 1);

    auto fillMode = m_path->GetFillMode();

    m_path = nullptr;

    clearGeometries();

    transformedPath->AddRef();
    m_geometries.append(transformedPath.get());

    HRESULT hr = GraphicsContext::systemFactory()->CreateGeometryGroup(fillMode, m_geometries.data(), m_geometries.size(), &m_path);
    RELEASE_ASSERT(SUCCEEDED(hr));
    ASSERT(refCount(m_path.get()) == 1);
}

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::fastBoundingRectForStroke(const PlatformContextDirect2D& platformContext) const
{
    if (isNull())
        return FloatRect();

    float tolerance = 10;

    auto* strokeStyle = const_cast<PlatformContextDirect2D&>(platformContext).strokeStyle();

    D2D1_RECT_F bounds = { };
    if (!SUCCEEDED(m_path->GetWidenedBounds(platformContext.strokeThickness(), strokeStyle, nullptr, tolerance, &bounds)))
        return FloatRect();

    return bounds;
}

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

    PlatformContextDirect2D scratchContextD2D(scratchRenderTarget());
    GraphicsContext scratchContext(&scratchContextD2D, GraphicsContext::BitmapRenderingContextType::GPUMemory);

    if (applier)
        applier->strokeStyle(&scratchContext);

    return fastBoundingRectForStroke(scratchContextD2D);
}

void Path::openFigureAtCurrentPointIfNecessary()
{
    if (m_figureIsOpened)
        return;

    if (!m_activePath) {
        COMPtr<ID2D1PathGeometry> activePathGeometry;
        GraphicsContext::systemFactory()->CreatePathGeometry(&activePathGeometry);
        HRESULT hr = activePathGeometry->Open(&m_activePath);
        RELEASE_ASSERT(SUCCEEDED(hr));
        appendGeometry(activePathGeometry.leakRef());
        ASSERT(refCount(m_activePath.get()) == 1);
    }

    m_activePath->SetFillMode(D2D1_FILL_MODE_WINDING);
    m_activePath->BeginFigure(currentPoint(), D2D1_FIGURE_BEGIN_FILLED);
    m_figureIsOpened = true;
}

void Path::moveTo(const FloatPoint& point)
{
    if (m_activePath)
        closeAnyOpenGeometries(D2D1_FIGURE_END_OPEN);

    COMPtr<ID2D1PathGeometry> activePathGeometry;
    GraphicsContext::systemFactory()->CreatePathGeometry(&activePathGeometry);

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

    appendGeometry(activePathGeometry.leakRef());

    ASSERT(refCount(m_activePath.get()) == 1);

    m_activePath->SetFillMode(D2D1_FILL_MODE_WINDING);
    m_activePath->BeginFigure(point, D2D1_FIGURE_BEGIN_FILLED);
    m_figureIsOpened = true;
}

void Path::addLineTo(const FloatPoint& point)
{
    openFigureAtCurrentPointIfNecessary();
    m_activePath->AddLine(point);
}

void Path::addQuadCurveTo(const FloatPoint& cp, const FloatPoint& p)
{
    openFigureAtCurrentPointIfNecessary();
    m_activePath->AddQuadraticBezier(D2D1::QuadraticBezierSegment(cp, p));
}

void Path::addBezierCurveTo(const FloatPoint& cp1, const FloatPoint& cp2, const FloatPoint& p)
{
    openFigureAtCurrentPointIfNecessary();
    m_activePath->AddBezier(D2D1::BezierSegment(cp1, cp2, p));
}

void Path::addArcTo(const FloatPoint& p1, const FloatPoint& p2, float radius)
{
    FloatPoint p0 = currentPoint();

    if (p1 == p0 || p1 == p2 || WTF::areEssentiallyEqual(radius, 0.0f))
        return addLineTo(p1);

    float direction = (p2.x() - p1.x()) * (p0.y() - p1.y()) + (p2.y() - p1.y()) * (p1.x() - p0.x());
    if (WTF::areEssentiallyEqual(direction, 0.0f))
        return addLineTo(p1);

    auto a2 = toFloatPoint(p0 - p1).lengthSquared();
    auto b2 = toFloatPoint(p1 - p2).lengthSquared();
    auto c2 = toFloatPoint(p0 - p2).lengthSquared();

    double cosx = (a2 + b2 - c2) / (2.0 * std::sqrt(a2 * b2));
    double sinx = std::sqrt(1.0 - cosx * cosx);
    double d = radius / ((1 - cosx) / sinx);

    auto an = toFloatPoint(p1 - p0).scaled(1.0 / std::sqrt(a2));
    auto bn = toFloatPoint(p1 - p2).scaled(1.0 / std::sqrt(b2));

    auto startPoint = toFloatPoint(p1 - an.scaled(d));
    auto p4 = toFloatPoint(p1 - bn.scaled(d));

    bool anticlockwise = (direction < 0);
    an.scale(radius * (anticlockwise ? 1 : -1));

    FloatPoint center(startPoint.x() + an.y(), startPoint.y() - an.x());

    double angle0 = atan2(startPoint.y() - center.y(), startPoint.x() - center.x());
    double angle1 = atan2(p4.y() - center.y(), p4.x() - center.x());

    openFigureAtCurrentPointIfNecessary();
    addLineTo(startPoint);
    addArc(center, radius, angle0, angle1, anticlockwise);
}

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());
        ASSERT(refCount(roundRect.get()) == 2);
        return;
    }

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

void Path::closeSubpath()
{
    if (isNull()) {
        m_activePath = nullptr;
        return;
    }

    if (!m_activePath) {
        ASSERT(!m_figureIsOpened);
        return;
    }

    closeAnyOpenGeometries(D2D1_FIGURE_END_CLOSED);
}

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;
}

const float twoPi = 2.0f * piFloat;

static void drawArcSection(ID2D1GeometrySink* sink, const FloatPoint& center, float radius, float startAngle, float endAngle, bool anticlockwise)
{
    // 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 endPoint = center;
    float endX = radius * std::cos(endAngle);
    float endY = radius * std::sin(endAngle);
    endPoint.move(endX, endY);

    D2D1_SWEEP_DIRECTION direction = anticlockwise ? D2D1_SWEEP_DIRECTION_COUNTER_CLOCKWISE : D2D1_SWEEP_DIRECTION_CLOCKWISE;
    sink->AddArc(D2D1::ArcSegment(endPoint, D2D1::SizeF(radius, radius), 0, direction, D2D1_ARC_SIZE_SMALL));
}

void Path::addArc(const FloatPoint& center, float radius, float startAngle, float endAngle, bool anticlockwise)
{
    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);
    }

    if (WTF::areEssentiallyEqual(std::abs(endAngle - startAngle), twoPi))
        return addEllipse(FloatRect(center.x() - radius, center.y() - radius, 2.0 * radius, 2.0 * radius));

    if (anticlockwise) {
        if (endAngle > startAngle) {
            endAngle -= twoPi * std::ceil((endAngle - startAngle) / twoPi);
            ASSERT(endAngle <= startAngle);
        }
    } else {
        if (startAngle > endAngle) {
            startAngle -= twoPi * std::ceil((startAngle - endAngle) / twoPi);
            ASSERT(startAngle <= endAngle);
        }
    }

    const float delta = anticlockwise ? -piOverTwoFloat : piOverTwoFloat;
    float remainingArcAngle = endAngle - startAngle;

    while ((remainingArcAngle > 0 && remainingArcAngle > delta) || (remainingArcAngle < 0 && remainingArcAngle < delta)) {
        const double currentEndAngle = startAngle + delta;
        drawArcSection(m_activePath.get(), center, radius, startAngle, currentEndAngle, anticlockwise);
        startAngle = currentEndAngle;
        remainingArcAngle -= delta;
    }

    // Handle any remaining part of the arc:
    if (std::abs(remainingArcAngle) > 1e-6)
        drawArcSection(m_activePath.get(), center, radius, startAngle, startAngle + remainingArcAngle, anticlockwise);
}

void Path::addRect(const FloatRect& r)
{
    if (!m_activePath)
        moveTo(r.location());

    COMPtr<ID2D1RectangleGeometry> rectangle;
    HRESULT hr = GraphicsContext::systemFactory()->CreateRectangleGeometry(r, &rectangle);
    RELEASE_ASSERT(SUCCEEDED(hr));
    appendGeometry(rectangle.get());
    ASSERT(refCount(rectangle.get()) == 2);
}

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)
{
    if (!m_activePath)
        moveTo(r.location());

    COMPtr<ID2D1EllipseGeometry> ellipse;
    // Note: The radii of the ellipse contained within a rectange are half the width and height of the rect.
    HRESULT hr = GraphicsContext::systemFactory()->CreateEllipseGeometry(D2D1::Ellipse(r.center(), 0.5 * r.width(), 0.5 * r.height()), &ellipse);
    RELEASE_ASSERT(SUCCEEDED(hr));
    appendGeometry(ellipse.get());
    ASSERT(refCount(ellipse.get()) == 2);
}

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;
    clearGeometries();
}

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

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

    ASSERT(m_path->GetSourceGeometryCount() == m_geometries.size());

    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)
