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

#ifndef SkContourMeasure_DEFINED
#define SkContourMeasure_DEFINED

#include "include/core/SkPathTypes.h" // IWYU pragma: keep
#include "include/core/SkPoint.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkScalar.h"
#include "include/core/SkSpan.h"
#include "include/core/SkTypes.h"
#include "include/private/base/SkTDArray.h"

#include <cstddef>
#include <memory>

class SkMatrix;
class SkPath;
class SkPathBuilder;

class SK_API SkContourMeasure : public SkRefCnt {
public:
    /** Return the length of the contour.
     */
    SkScalar length() const { return fLength; }

    /** Pins distance to 0 <= distance <= length(), and then computes the corresponding
     *  position and tangent.
     */
    [[nodiscard]] bool getPosTan(SkScalar distance, SkPoint* position, SkVector* tangent) const;

    enum MatrixFlags {
        kGetPosition_MatrixFlag     = 0x01,
        kGetTangent_MatrixFlag      = 0x02,
        kGetPosAndTan_MatrixFlag    = kGetPosition_MatrixFlag | kGetTangent_MatrixFlag
    };

    /** Pins distance to 0 <= distance <= getLength(), and then computes
     the corresponding matrix (by calling getPosTan).
     Returns false if there is no path, or a zero-length path was specified, in which case
     matrix is unchanged.
     */
    [[nodiscard]] bool getMatrix(SkScalar distance, SkMatrix* matrix,
                                 MatrixFlags flags = kGetPosAndTan_MatrixFlag) const;

    /** Given a start and stop distance, return in dst the intervening segment(s).
     If the segment is zero-length, return false, else return true.
     startD and stopD are pinned to legal values (0..getLength()). If startD > stopD
     then return false (and leave dst untouched).
     Begin the segment with a moveTo if startWithMoveTo is true
     */
    [[nodiscard]] bool getSegment(SkScalar startD, SkScalar stopD, SkPathBuilder* dst,
                                  bool startWithMoveTo) const;
#ifdef SK_SUPPORT_MUTABLE_PATHEFFECT
    [[nodiscard]] bool getSegment(SkScalar startD, SkScalar stopD, SkPath* dst,
                                  bool startWithMoveTo) const;
#endif

    /** Return true if the contour is closed()
     */
    bool isClosed() const { return fIsClosed; }

    /** Measurement data for individual verbs.
     */
    struct VerbMeasure {
        SkScalar              fDistance; // Cumulative distance along the current contour.
        SkPathVerb            fVerb;     // Verb type.
        SkSpan<const SkPoint> fPts;      // Verb points.
    };

private:
    struct Segment;

public:
    /** Utility for iterating over the current contour verbs:
     *
     *   for (const auto verb_measure : contour_measure) {
     *     ...
     *   }
     */
    class ForwardVerbIterator final {
    public:
        VerbMeasure operator*() const;

        ForwardVerbIterator& operator++() {
            SkASSERT(!fSegments.empty());

            fSegments = LastSegForCurrentVerb(fSegments.subspan(1));

            return *this;
        }

        bool operator==(const ForwardVerbIterator& other) const {
            SkASSERT(fSegments.data() != other.fSegments.data() ||
                     fSegments.size() == other.fSegments.size());
            return fSegments.data() == other.fSegments.data();
        }

        bool operator!=(const ForwardVerbIterator& other) const {
            return !((*this) == other);
        }

    private:
        friend class SkContourMeasure;

        ForwardVerbIterator(SkSpan<const Segment> segs, SkSpan<const SkPoint> pts)
            : fSegments(LastSegForCurrentVerb(segs))
            , fPts(pts) {}

        static SkSpan<const Segment> LastSegForCurrentVerb(const SkSpan<const Segment>& segs) {
            size_t i = 1;
            while (i < segs.size() && segs[0].fPtIndex == segs[i].fPtIndex) {
                ++i;
            }

            return segs.subspan(i - 1);
        }

        // Remaining segments for forward iteration. The first segment in the span is
        // adjusted to always point to the last segment of the current verb, such that its distance
        // corresponds to the verb distance.
        SkSpan<const Segment> fSegments;

        // All path points (indexed in segments).
        SkSpan<const SkPoint> fPts;
    };

    ForwardVerbIterator begin() const {
        return ForwardVerbIterator(fSegments, fPts);
    }
    ForwardVerbIterator end() const {
        return ForwardVerbIterator(SkSpan(fSegments.end(), 0), fPts);
    }

private:
    struct Segment {
        SkScalar    fDistance;  // total distance up to this point
        unsigned    fPtIndex; // index into the fPts array
        unsigned    fTValue : 30;
        unsigned    fType : 2;  // actually the enum SkSegType
        // See SkPathMeasurePriv.h

        SkScalar getScalarT() const;

        static const Segment* Next(const Segment* seg) {
            unsigned ptIndex = seg->fPtIndex;
            do {
                ++seg;
            } while (seg->fPtIndex == ptIndex);
            return seg;
        }

    };

    const SkTDArray<Segment>  fSegments;
    const SkTDArray<SkPoint>  fPts; // Points used to define the segments

    const SkScalar fLength;
    const bool fIsClosed;

    SkContourMeasure(SkTDArray<Segment>&& segs, SkTDArray<SkPoint>&& pts,
                     SkScalar length, bool isClosed);
    ~SkContourMeasure() override {}

    const Segment* distanceToSegment(SkScalar distance, SkScalar* t) const;

    friend class SkContourMeasureIter;
    friend class SkPathMeasurePriv;
};

class SK_API SkContourMeasureIter {
public:
    SkContourMeasureIter();
    /**
     *  Initialize the Iter with a path.
     *  The parts of the path that are needed are copied, so the client is free to modify/delete
     *  the path after this call.
     *
     *  resScale controls the precision of the measure. values > 1 increase the
     *  precision (and possibly slow down the computation).
     */
    SkContourMeasureIter(const SkPath& path, bool forceClosed, SkScalar resScale = 1);
    ~SkContourMeasureIter();

    SkContourMeasureIter(SkContourMeasureIter&&);
    SkContourMeasureIter& operator=(SkContourMeasureIter&&);

    /**
     *  Reset the Iter with a path.
     *  The parts of the path that are needed are copied, so the client is free to modify/delete
     *  the path after this call.
     */
    void reset(const SkPath& path, bool forceClosed, SkScalar resScale = 1);

    /**
     *  Iterates through contours in path, returning a contour-measure object for each contour
     *  in the path. Returns null when it is done.
     *
     *  This only returns non-zero length contours, where a contour is the segments between
     *  a kMove_Verb and either ...
     *      - the next kMove_Verb
     *      - kClose_Verb (1 or more)
     *      - kDone_Verb
     *  If it encounters a zero-length contour, it is skipped.
     */
    sk_sp<SkContourMeasure> next();

private:
    class Impl;

    std::unique_ptr<Impl> fImpl;
};

#endif
