/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "SkOpContour.h"
#include "SkPath.h"

#ifdef SK_DEBUG
#include "SkPathOpsPoint.h"
#endif

class SkIntersectionHelper {
public:
    enum SegmentType {
        kHorizontalLine_Segment = -1,
        kVerticalLine_Segment = 0,
        kLine_Segment = SkPath::kLine_Verb,
        kQuad_Segment = SkPath::kQuad_Verb,
        kCubic_Segment = SkPath::kCubic_Verb,
    };

    bool addCoincident(SkIntersectionHelper& other, const SkIntersections& ts, bool swap) {
        return fContour->addCoincident(fIndex, other.fContour, other.fIndex, ts, swap);
    }

    // FIXME: does it make sense to write otherIndex now if we're going to
    // fix it up later?
    void addOtherT(int index, double otherT, int otherIndex) {
        fContour->addOtherT(fIndex, index, otherT, otherIndex);
    }

    bool addPartialCoincident(SkIntersectionHelper& other, const SkIntersections& ts, int index,
            bool swap) {
        return fContour->addPartialCoincident(fIndex, other.fContour, other.fIndex, ts, index,
                swap);
    }

    // Avoid collapsing t values that are close to the same since
    // we walk ts to describe consecutive intersections. Since a pair of ts can
    // be nearly equal, any problems caused by this should be taken care
    // of later.
    // On the edge or out of range values are negative; add 2 to get end
    int addT(const SkIntersectionHelper& other, const SkPoint& pt, double newT) {
        return fContour->addT(fIndex, other.fContour, other.fIndex, pt, newT);
    }

    int addSelfT(const SkPoint& pt, double newT) {
        return fContour->addSelfT(fIndex, pt, newT);
    }

    bool advance() {
        return ++fIndex < fLast;
    }

    SkScalar bottom() const {
        return bounds().fBottom;
    }

    const SkPathOpsBounds& bounds() const {
        return fContour->segments()[fIndex].bounds();
    }

    void init(SkOpContour* contour) {
        fContour = contour;
        fIndex = 0;
        fLast = contour->segments().count();
    }

    bool isAdjacent(const SkIntersectionHelper& next) {
        return fContour == next.fContour && fIndex + 1 == next.fIndex;
    }

    bool isFirstLast(const SkIntersectionHelper& next) {
        return fContour == next.fContour && fIndex == 0
                && next.fIndex == fLast - 1;
    }

    bool isPartial(double t1, double t2, const SkDPoint& pt1, const SkDPoint& pt2) const {
        const SkOpSegment& segment = fContour->segments()[fIndex];
        double mid = (t1 + t2) / 2;
        SkDPoint midPtByT = segment.dPtAtT(mid);
        SkDPoint midPtByAvg = SkDPoint::Mid(pt1, pt2);
        return midPtByT.approximatelyPEqual(midPtByAvg);
    }

    SkScalar left() const {
        return bounds().fLeft;
    }

    const SkPoint* pts() const {
        return fContour->segments()[fIndex].pts();
    }

    SkScalar right() const {
        return bounds().fRight;
    }

    SegmentType segmentType() const {
        const SkOpSegment& segment = fContour->segments()[fIndex];
        SegmentType type = (SegmentType) segment.verb();
        if (type != kLine_Segment) {
            return type;
        }
        if (segment.isHorizontal()) {
            return kHorizontalLine_Segment;
        }
        if (segment.isVertical()) {
            return kVerticalLine_Segment;
        }
        return kLine_Segment;
    }

    bool startAfter(const SkIntersectionHelper& after) {
        fIndex = after.fIndex;
        return advance();
    }

    SkScalar top() const {
        return bounds().fTop;
    }

    SkPath::Verb verb() const {
        return fContour->segments()[fIndex].verb();
    }

    SkScalar x() const {
        return bounds().fLeft;
    }

    bool xFlipped() const {
        return x() != pts()[0].fX;
    }

    SkScalar y() const {
        return bounds().fTop;
    }

    bool yFlipped() const {
        return y() != pts()[0].fY;
    }

private:
    // utility callable by the user from the debugger when the implementation code is linked in
    void dump() const;

    SkOpContour* fContour;
    int fIndex;
    int fLast;
};
