/*
 * Copyright 2015 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef SkPathPriv_DEFINED
#define SkPathPriv_DEFINED

#include "include/core/SkArc.h"
#include "include/core/SkPath.h"
#include "include/core/SkPathBuilder.h"
#include "include/core/SkPathTypes.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkScalar.h"
#include "include/core/SkSpan.h"
#include "include/core/SkTypes.h"
#include "include/private/SkDebug.h"
#include "include/private/SkIDChangeListener.h"
#include "include/private/SkPathRef.h"
#include "src/core/SkPathData.h"
#include "src/core/SkPathEnums.h"
#include "src/core/SkPathRaw.h"

#include <cstddef>
#include <cstdint>
#include <iterator>
#include <optional>
#include <utility>

class SkMatrix;
class SkRRect;

static_assert(0 == static_cast<int>(SkPathFillType::kWinding), "fill_type_mismatch");
static_assert(1 == static_cast<int>(SkPathFillType::kEvenOdd), "fill_type_mismatch");
static_assert(2 == static_cast<int>(SkPathFillType::kInverseWinding), "fill_type_mismatch");
static_assert(3 == static_cast<int>(SkPathFillType::kInverseEvenOdd), "fill_type_mismatch");

class SkPathPriv {
public:
    enum class RRectAsEnum {
        kRect, kOval, kRRect,
    };
    static std::pair<RRectAsEnum, unsigned> SimplifyRRect(const SkRRect& rr, unsigned startIndex) {
        if (rr.isRect() || rr.isEmpty()) {
            return { RRectAsEnum::kRect, (startIndex + 1) / 2 };
        }
        if (rr.isOval()) {
            return { RRectAsEnum::kOval, startIndex / 2 };
        }
        return { RRectAsEnum::kRRect, startIndex };
    }

    static SkPathConvexity ComputeConvexity(SkSpan<const SkPoint> pts,
                                            SkSpan<const SkPathVerb> verbs,
                                            SkSpan<const float> conicWeights);

    static SkPathConvexity TransformConvexity(const SkMatrix&, SkSpan<const SkPoint>,
                                              SkPathConvexity);

    static uint8_t ComputeSegmentMask(SkSpan<const SkPathVerb>);

    /* Note: does NOT use convexity in the raw, so it need not be resolved,
     *       if converting from builder or path.
     */
    static bool Contains(const SkPathRaw&, SkPoint);

    // skbug.com/40041027: Not a perfect solution for W plane clipping, but 1/16384 is a
    // reasonable limit (roughly 5e-5)
    inline static constexpr SkScalar kW0PlaneDistance = 1.f / (1 << 14);

    static SkPathFirstDirection AsFirstDirection(SkPathDirection dir) {
        // since we agree numerically for the values in Direction, we can just cast.
        return (SkPathFirstDirection)dir;
    }

    /**
     *  Return the opposite of the specified direction. kUnknown is its own
     *  opposite.
     */
    static SkPathFirstDirection OppositeFirstDirection(SkPathFirstDirection dir) {
        static const SkPathFirstDirection gOppositeDir[] = {
            SkPathFirstDirection::kCCW, SkPathFirstDirection::kCW, SkPathFirstDirection::kUnknown,
        };
        return gOppositeDir[(unsigned)dir];
    }

    /**
     *  Tries to compute the direction of the outer-most non-degenerate
     *  contour. If it can be computed, return that direction. If it cannot be determined,
     *  or the contour is known to be convex, return kUnknown. If the direction was determined,
     *  it is cached to make subsequent calls return quickly.
     */
    static SkPathFirstDirection ComputeFirstDirection(const SkPathRaw&);
    static SkPathFirstDirection ComputeFirstDirection(const SkPath&);

    static bool IsClosedSingleContour(SkSpan<const SkPathVerb> verbs) {
        if (verbs.empty()) {
            return false;
        }

        int moveCount = 0;
        for (const auto& verb : verbs) {
            switch (verb) {
                case SkPathVerb::kMove:
                    if (++moveCount > 1) {
                        return false;
                    }
                    break;
                case SkPathVerb::kClose:
                    return &verb == &verbs.back();
                default:
                    break;
            }
        }
        return false;
    }

    static bool IsClosedSingleContour(const SkPath& path) {
        return IsClosedSingleContour(path.verbs());
    }

    /*
     *  Returns the index of the last moveTo() point, based on the verbs.
     *  If verbs is empty / ptCount == 0, then this returns -1.
     */
    static int FindLastMoveToIndex(SkSpan<const SkPathVerb> verbs, const size_t ptCount);

    /*
     *  If we're transforming a known shape (oval or rrect), this computes what happens to its
     *  - winding direction
     *  - start index
     */
    static std::pair<SkPathDirection, unsigned>
    TransformDirAndStart(const SkMatrix&, bool isRRect, SkPathDirection dir, unsigned start);

    static void AddGenIDChangeListener(const SkPath&, sk_sp<SkIDChangeListener>);

    /**
     * This returns the info for a rect that has a move followed by 3 or 4 lines and a close. If
     * 'isSimpleFill' is true, an uncloseed rect will also be accepted as long as it starts and
     * ends at the same corner. This does not permit degenerate line or point rectangles.
     */
    static std::optional<SkPathRectInfo> IsSimpleRect(const SkPath& path, bool isSimpleFill);

    // Asserts the path contour was built from RRect, so it does not return
    // an optional. This exists so path's can have a flag that they are really
    // a RRect, without having to actually store the 4 radii... since those can
    // be deduced from the contour itself.
    //
    static SkRRect DeduceRRectFromContour(const SkRect& bounds,
                                          SkSpan<const SkPoint>, SkSpan<const SkPathVerb>);

    /**
     * Creates a path from arc params using the semantics of SkCanvas::drawArc. This function
     * assumes empty ovals and zero sweeps have already been filtered out.
     */
    static SkPath CreateDrawArcPath(const SkArc& arc, bool isFillNoPathEffect);

    /**
     * Determines whether an arc produced by CreateDrawArcPath will be convex. Assumes a non-empty
     * oval.
     */
    static bool DrawArcIsConvex(SkScalar sweepAngle, SkArc::Type arcType, bool isFillNoPathEffect);

    /**
      * Iterates through a raw range of path verbs, points, and conics. All values are returned
      * unaltered.
      *
      * NOTE: This class's definition will be moved into SkPathPriv once RangeIter is removed.
    */
    using RangeIter = SkPath::RangeIter;

    /**
     * Iterable object for traversing verbs, points, and conic weights in a path:
     *
     *   for (auto [verb, pts, weights] : SkPathPriv::Iterate(skPath)) {
     *       ...
     *   }
     */
    struct Iterate {
    public:
        Iterate(SkPath&&) = delete;
        Iterate(const SkPath& path)
            : Iterate(path.verbs(), path.points().data(), path.conicWeights().data())
        {
            // Don't allow iteration through non-finite points.
            if (!path.isFinite()) {
                fVerbsBegin = fVerbsEnd;
            }
        }
        Iterate(SkSpan<const SkPathVerb> verbs, const SkPoint* points, const SkScalar* weights)
            : fVerbsBegin(verbs.data())
            , fVerbsEnd(verbs.data() + verbs.size())
            , fPoints(points)
            , fWeights(weights)
        {}
        SkPath::RangeIter begin() { return {fVerbsBegin, fPoints, fWeights}; }
        SkPath::RangeIter end() { return {fVerbsEnd, nullptr, nullptr}; }
    private:
        const SkPathVerb* fVerbsBegin;
        const SkPathVerb* fVerbsEnd;
        const SkPoint* fPoints;
        const SkScalar* fWeights;
    };

    // returns Empty() if there are no points
    static SkRect ComputeTightBounds(SkSpan<const SkPoint> points,
                                     SkSpan<const SkPathVerb> verbs,
                                     SkSpan<const float> conicWeights);

    /** Returns the oval info if this path was created as an oval or circle, else returns {}.
     */
    static std::optional<SkPathOvalInfo> IsOval(const SkPath& path) {
        return path.getOvalInfo();
    }

    /** Returns the rrect info if this path was created as one, else returns {}.
     */
    static std::optional<SkPathRRectInfo> IsRRect(const SkPath& path) {
        return path.getRRectInfo();
    }

    /**
     *  Sometimes in the drawing pipeline, we have to perform math on path coordinates, even after
     *  the path is in device-coordinates. Tessellation and clipping are two examples. Usually this
     *  is pretty modest, but it can involve subtracting/adding coordinates, or multiplying by
     *  small constants (e.g. 2,3,4). To try to preflight issues where these optionations could turn
     *  finite path values into infinities (or NaNs), we allow the upper drawing code to reject
     *  the path if its bounds (in device coordinates) is too close to max float.
     */
    static bool TooBigForMath(const SkRect& bounds) {
        // This value is just a guess. smaller is safer, but we don't want to reject largish paths
        // that we don't have to.
        constexpr SkScalar scale_down_to_allow_for_small_multiplies = 0.25f;
        constexpr SkScalar max = SK_ScalarMax * scale_down_to_allow_for_small_multiplies;

        // use ! expression so we return true if bounds contains NaN
        return !(bounds.fLeft >= -max && bounds.fTop >= -max &&
                 bounds.fRight <= max && bounds.fBottom <= max);
    }

    // Returns number of valid points for each SkPath::Iter verb
    static int PtsInIter(unsigned verb) {
        static const uint8_t gPtsInVerb[] = {
            1,  // kMove    pts[0]
            2,  // kLine    pts[0..1]
            3,  // kQuad    pts[0..2]
            3,  // kConic   pts[0..2]
            4,  // kCubic   pts[0..3]
            0,  // kClose
            0   // kDone
        };

        SkASSERT(verb < std::size(gPtsInVerb));
        return gPtsInVerb[verb];
    }

    static int PtsInIter(SkPathVerb verb) { return PtsInIter((unsigned)verb); }

    // Returns number of valid points for each verb, not including the "starter"
    // point that the Iterator adds for line/quad/conic/cubic
    static int PtsInVerb(unsigned verb) {
        static const uint8_t gPtsInVerb[] = {
            1,  // kMove    pts[0]
            1,  // kLine    pts[0..1]
            2,  // kQuad    pts[0..2]
            2,  // kConic   pts[0..2]
            3,  // kCubic   pts[0..3]
            0,  // kClose
            0   // kDone
        };

        SkASSERT(verb < std::size(gPtsInVerb));
        return gPtsInVerb[verb];
    }

    static int PtsInVerb(SkPathVerb verb) { return PtsInVerb((unsigned)verb); }

    static bool IsAxisAligned(SkSpan<const SkPoint>);

    static bool AllPointsEq(SkSpan<const SkPoint> pts) {
        for (size_t i = 1; i < pts.size(); ++i) {
            if (pts[0] != pts[i]) {
                return false;
            }
        }
        return true;
    }

    struct RectContour {
        SkRect          fRect;
        bool            fIsClosed;
        SkPathDirection fDirection;
        size_t          fPointsConsumed,
                        fVerbsConsumed;
    };
    static std::optional<RectContour> IsRectContour(SkSpan<const SkPoint> ptSpan,
                                                    SkSpan<const SkPathVerb> vbSpan,
                                                    uint32_t segmentMask,
                                                    bool allowPartial);

    /** Returns true if SkPath is equivalent to nested SkRect pair when filled.
     If false, rect and dirs are unchanged.
     If true, rect and dirs are written to if not nullptr:
     setting rect[0] to outer SkRect, and rect[1] to inner SkRect;
     setting dirs[0] to SkPathDirection of outer SkRect, and dirs[1] to SkPathDirection of
     inner SkRect.

     @param rect  storage for SkRect pair; may be nullptr
     @param dirs  storage for SkPathDirection pair; may be nullptr
     @return      true if SkPath contains nested SkRect pair
     */
    static bool IsNestedFillRects(const SkPathRaw&, SkRect rect[2],
                                  SkPathDirection dirs[2] = nullptr);

    static bool IsNestedFillRects(const SkPath& path, SkRect rect[2],
                                  SkPathDirection dirs[2] = nullptr) {
        auto raw = Raw(path, SkResolveConvexity::kNo);
        return raw.has_value() && IsNestedFillRects(*raw, rect, dirs);
    }


    static bool IsInverseFillType(SkPathFillType fill) {
        return (static_cast<int>(fill) & 2) != 0;
    }

    /**
     *  If needed (to not blow-up under a perspective matrix), clip the path, returning the
     *  answer in "result", and return true.
     *
     *  Note result might be empty (if the path was completely clipped out).
     *
     *  If no clipping is needed, returns false and "result" is left unchanged.
     */
    static bool PerspectiveClip(const SkPath& src, const SkMatrix&, SkPath* result);

    /**
     * Gets the number of GenIDChangeListeners. If another thread has access to this path then
     * this may be stale before return and only indicates that the count was the return value
     * at some point during the execution of the function.
     */
    static int GenIDChangeListenersCount(const SkPath&);

    static SkPathConvexity GetConvexity(const SkPath& path) {
        return path.getConvexity();
    }
    static SkPathConvexity GetConvexityOrUnknown(const SkPath& path) {
        return path.getConvexityOrUnknown();
    }
    static void SetConvexity(const SkPath& path, SkPathConvexity c) {
        path.setConvexity(c);
    }
    static void ForceComputeConvexity(const SkPath& path) {
        path.setConvexity(SkPathConvexity::kUnknown);
        (void)path.isConvex();
    }

    static SkPathConvexity GetConvexityOrUnknown(const SkPathData& pdata) {
        return pdata.getConvexityOrUnknown();
    }

    static void ReverseAddPath(SkPathBuilder* builder, const SkPath& reverseMe) {
        builder->privateReverseAddPath(reverseMe);
    }

    static void ReversePathTo(SkPathBuilder* builder, const SkPath& reverseMe) {
        builder->privateReversePathTo(reverseMe);
    }

    static SkPath ReversePath(const SkPath& reverseMe) {
        SkPathBuilder bu;
        bu.privateReverseAddPath(reverseMe);
        return bu.detach();
    }

    static SkSpan<const SkPathVerb> GetVerbs(const SkPathBuilder& builder) {
        return builder.fVerbs;
    }

    static int CountVerbs(const SkPathBuilder& builder) {
        return builder.fVerbs.size();
    }

    static std::optional<SkPathRaw> Raw(const SkPath& path, SkResolveConvexity rc) {
        return path.raw(rc);
    }

    static std::optional<SkPathRaw> Raw(const SkPathBuilder& builder, SkResolveConvexity rc) {
        const auto bounds = builder.computeFiniteBounds();
        if (!bounds) {
            return {};
        }

        SkPathConvexity convexity = builder.fConvexity;
        if (convexity == SkPathConvexity::kUnknown && rc == SkResolveConvexity::kYes) {
            convexity = SkPathPriv::ComputeConvexity(builder.fPts,
                                                     builder.fVerbs,
                                                     builder.fConicWeights);
        }

        return SkPathRaw{
            builder.points(),
            builder.verbs(),
            builder.conicWeights(),
            *bounds,
            builder.fillType(),
            convexity,
            SkTo<uint8_t>(builder.fSegmentMask),
        };
    }

    // Returns Empty if there are no points
    // Returns {} if the bounds are not finite
    static std::optional<SkRect> TrimmedBounds(SkSpan<const SkPoint> pts,
                                               SkSpan<const SkPathVerb> vbs) {
        // Does a trailing kMove verb contribute to the bounds?
        // - only if it is the only verb in the path
        // - otherwise we ignore it when computing bounds
        if (vbs.size() > 1 && vbs.back() == SkPathVerb::kMove) {
            SkASSERT(pts.size() > 0);
            // While trailing moves do not contribute to the bounds, we still reject them.
            if (!pts.back().isFinite()) {
                return {};
            }
            pts = pts.subspan(0, pts.size() - 1);
        }
        return SkRect::Bounds(pts);
    }
};

// Lightweight variant of SkPath::Iter that only returns segments (e.g. lines/conics).
// Does not return kMove or kClose.
// Always "auto-closes" each contour.
// Roughly the same as SkPath::Iter(path, true), but does not return moves or closes
//
class SkPathEdgeIter {
    const SkPathVerb* fVerbs;
    const SkPathVerb* fVerbsStop;
    const SkPoint*  fPts;
    const SkPoint*  fMoveToPtr;
    const SkScalar* fConicWeights;
    SkPoint         fScratch[2];    // for auto-close lines
    bool            fNeedsCloseLine;
    bool            fNextIsNewContour;
    SkDEBUGCODE(bool fIsConic;)

public:
    SkPathEdgeIter(const SkPath& path);
    SkPathEdgeIter(const SkPathRaw&);

    SkScalar conicWeight() const {
        SkASSERT(fIsConic);
        return *fConicWeights;
    }

    enum class Edge {
        kLine = (int)SkPathVerb::kLine,
        kQuad = (int)SkPathVerb::kQuad,
        kConic = (int)SkPathVerb::kConic,
        kCubic = (int)SkPathVerb::kCubic,
 //       kInvalid = 99,
    };

    static SkPathVerb EdgeToVerb(Edge e) {
        return SkPathVerb(e);
    }

    // todo: return as optional? fPts become span?
    struct Result {
        const SkPoint*  fPts;   // points for the segment, or null if done
        Edge            fEdge;
        bool            fIsNewContour;

        // Returns true when it holds an Edge, false when the path is done.
        explicit operator bool() { return fPts != nullptr; }
    };

    Result next() {
        auto closeline = [&]() {
            fScratch[0] = fPts[-1];
            fScratch[1] = *fMoveToPtr;
            fNeedsCloseLine = false;
            fNextIsNewContour = true;
            return Result{ fScratch, Edge::kLine, false };
        };

        for (;;) {
            SkASSERT(fVerbs <= fVerbsStop);
            if (fVerbs == fVerbsStop) {
                return fNeedsCloseLine ? closeline() : Result{nullptr, Edge::kLine, false};
            }

            SkDEBUGCODE(fIsConic = false;)

            const auto verb = *fVerbs++;
            switch (verb) {
                case SkPathVerb::kMove: {
                    if (fNeedsCloseLine) {
                        auto res = closeline();
                        fMoveToPtr = fPts++;
                        return res;
                    }
                    fMoveToPtr = fPts++;
                    fNextIsNewContour = true;
                } break;
                case SkPathVerb::kClose:
                    if (fNeedsCloseLine) return closeline();
                    break;
                default: {
                    unsigned v = static_cast<unsigned>(verb);
                    // Actual edge.
                    const int pts_count = (v+2) / 2,
                              cws_count = (v & (v-1)) / 2;
                    SkASSERT(pts_count == SkPathPriv::PtsInIter(v) - 1);

                    fNeedsCloseLine = true;
                    fPts           += pts_count;
                    fConicWeights  += cws_count;

                    SkDEBUGCODE(fIsConic = (verb == SkPathVerb::kConic);)
                    SkASSERT(fIsConic == (cws_count > 0));

                    bool isNewContour = fNextIsNewContour;
                    fNextIsNewContour = false;
                    return { &fPts[-(pts_count + 1)], Edge(v), isNewContour };
                }
            }
        }
    }
};

#endif
