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

#include "SkPathOpsDebug.h"
#include "SkPathOpsTypes.h"
#include "SkPoint.h"

class SkArenaAlloc;
class SkOpAngle;
class SkOpContour;
class SkOpGlobalState;
class SkOpSegment;
class SkOpSpanBase;
class SkOpSpan;
struct SkPathOpsBounds;

// subset of op span used by terminal span (when t is equal to one)
class SkOpPtT {
public:
    enum {
        kIsAlias = 1,
        kIsDuplicate = 1
    };

    const SkOpPtT* active() const;

    // please keep in sync with debugAddOpp()
    void addOpp(SkOpPtT* opp, SkOpPtT* oppPrev) {
        SkOpPtT* oldNext = this->fNext;
        SkASSERT(this != opp);
        this->fNext = opp;
        SkASSERT(oppPrev != oldNext);
        oppPrev->fNext = oldNext;
    }

    bool alias() const;
    bool coincident() const { return fCoincident; }
    bool contains(const SkOpPtT* ) const;
    bool contains(const SkOpSegment*, const SkPoint& ) const;
    bool contains(const SkOpSegment*, double t) const;
    const SkOpPtT* contains(const SkOpSegment* ) const;
    SkOpContour* contour() const;

    int debugID() const {
        return SkDEBUGRELEASE(fID, -1);
    }

    void debugAddOpp(const SkOpPtT* opp, const SkOpPtT* oppPrev) const;
    const SkOpAngle* debugAngle(int id) const;
    const SkOpCoincidence* debugCoincidence() const;
    bool debugContains(const SkOpPtT* ) const;
    const SkOpPtT* debugContains(const SkOpSegment* check) const;
    SkOpContour* debugContour(int id) const;
    const SkOpPtT* debugEnder(const SkOpPtT* end) const;
    int debugLoopLimit(bool report) const;
    bool debugMatchID(int id) const;
    const SkOpPtT* debugOppPrev(const SkOpPtT* opp) const;
    const SkOpPtT* debugPtT(int id) const;
    void debugResetCoinT() const;
    const SkOpSegment* debugSegment(int id) const;
    void debugSetCoinT(int ) const;
    const SkOpSpanBase* debugSpan(int id) const;
    void debugValidate() const;

    bool deleted() const {
        return fDeleted;
    }

    bool duplicate() const {
        return fDuplicatePt;
    }

    void dump() const;  // available to testing only
    void dumpAll() const;
    void dumpBase() const;

    const SkOpPtT* find(const SkOpSegment* ) const;
    SkOpGlobalState* globalState() const;
    void init(SkOpSpanBase* , double t, const SkPoint& , bool dup);

    void insert(SkOpPtT* span) {
        SkASSERT(span != this);
        span->fNext = fNext;
        fNext = span;
    }

    const SkOpPtT* next() const {
        return fNext;
    }

    SkOpPtT* next() {
        return fNext;
    }

    bool onEnd() const;

    // returns nullptr if this is already in the opp ptT loop
    SkOpPtT* oppPrev(const SkOpPtT* opp) const {
        // find the fOpp ptr to opp
        SkOpPtT* oppPrev = opp->fNext;
        if (oppPrev == this) {
            return nullptr;
        }
        while (oppPrev->fNext != opp) {
            oppPrev = oppPrev->fNext;
            if (oppPrev == this) {
                return nullptr;
            }
        }
        return oppPrev;
    }

    static bool Overlaps(const SkOpPtT* s1, const SkOpPtT* e1, const SkOpPtT* s2,
            const SkOpPtT* e2, const SkOpPtT** sOut, const SkOpPtT** eOut) {
        const SkOpPtT* start1 = s1->fT < e1->fT ? s1 : e1;
        const SkOpPtT* start2 = s2->fT < e2->fT ? s2 : e2;
        *sOut = between(s1->fT, start2->fT, e1->fT) ? start2
                : between(s2->fT, start1->fT, e2->fT) ? start1 : nullptr;
        const SkOpPtT* end1 = s1->fT < e1->fT ? e1 : s1;
        const SkOpPtT* end2 = s2->fT < e2->fT ? e2 : s2;
        *eOut = between(s1->fT, end2->fT, e1->fT) ? end2
                : between(s2->fT, end1->fT, e2->fT) ? end1 : nullptr;
        if (*sOut == *eOut) {
            SkOPOBJASSERT(s1, start1->fT >= end2->fT || start2->fT >= end1->fT);
            return false;
        }
        SkASSERT(!*sOut || *sOut != *eOut);
        return *sOut && *eOut;
    }

    bool ptAlreadySeen(const SkOpPtT* head) const;
    SkOpPtT* prev();

    const SkOpSegment* segment() const;
    SkOpSegment* segment();

    void setCoincident() const {
        SkOPASSERT(!fDeleted);
        fCoincident = true;
    }

    void setDeleted();

    void setSpan(const SkOpSpanBase* span) {
        fSpan = const_cast<SkOpSpanBase*>(span);
    }

    const SkOpSpanBase* span() const {
        return fSpan;
    }

    SkOpSpanBase* span() {
        return fSpan;
    }

    const SkOpPtT* starter(const SkOpPtT* end) const {
        return fT < end->fT ? this : end;
    }

    double fT;
    SkPoint fPt;   // cache of point value at this t
protected:
    SkOpSpanBase* fSpan;  // contains winding data
    SkOpPtT* fNext;  // intersection on opposite curve or alias on this curve
    bool fDeleted;  // set if removed from span list
    bool fDuplicatePt;  // set if identical pt is somewhere in the next loop
    // below mutable since referrer is otherwise always const
    mutable bool fCoincident;  // set if at some point a coincident span pointed here
    SkDEBUGCODE(int fID);
};

class SkOpSpanBase {
public:
    void addOpp(SkOpSpanBase* opp);

    void bumpSpanAdds() {
        ++fSpanAdds;
    }

    bool chased() const {
        return fChased;
    }

    void checkForCollapsedCoincidence();

    const SkOpSpanBase* coinEnd() const {
        return fCoinEnd;
    }

    bool collapsed(double s, double e) const;
    bool contains(const SkOpSpanBase* ) const;
    const SkOpPtT* contains(const SkOpSegment* ) const;

    bool containsCoinEnd(const SkOpSpanBase* coin) const {
        SkASSERT(this != coin);
        const SkOpSpanBase* next = this;
        while ((next = next->fCoinEnd) != this) {
            if (next == coin) {
                return true;
            }
        }
        return false;
    }

    bool containsCoinEnd(const SkOpSegment* ) const;
    SkOpContour* contour() const;

    int debugBumpCount() {
        return SkDEBUGRELEASE(++fCount, -1);
    }

    int debugID() const {
        return SkDEBUGRELEASE(fID, -1);
    }

#if DEBUG_COIN
    void debugAddOpp(SkPathOpsDebug::GlitchLog* , const SkOpSpanBase* opp) const;
#endif
    bool debugAlignedEnd(double t, const SkPoint& pt) const;
    bool debugAlignedInner() const;
    const SkOpAngle* debugAngle(int id) const;
#if DEBUG_COIN
    void debugCheckForCollapsedCoincidence(SkPathOpsDebug::GlitchLog* ) const;
#endif
    const SkOpCoincidence* debugCoincidence() const;
    bool debugCoinEndLoopCheck() const;
    SkOpContour* debugContour(int id) const;
#ifdef SK_DEBUG
    bool debugDeleted() const { return fDebugDeleted; }
#endif
#if DEBUG_COIN
    void debugInsertCoinEnd(SkPathOpsDebug::GlitchLog* ,
                            const SkOpSpanBase* ) const;
    void debugMergeMatches(SkPathOpsDebug::GlitchLog* log,
                           const SkOpSpanBase* opp) const;
#endif
    const SkOpPtT* debugPtT(int id) const;
    void debugResetCoinT() const;
    const SkOpSegment* debugSegment(int id) const;
    void debugSetCoinT(int ) const;
#ifdef SK_DEBUG
    void debugSetDeleted() { fDebugDeleted = true; }
#endif
    const SkOpSpanBase* debugSpan(int id) const;
    const SkOpSpan* debugStarter(SkOpSpanBase const** endPtr) const;
    SkOpGlobalState* globalState() const;
    void debugValidate() const;

    bool deleted() const {
        return fPtT.deleted();
    }

    void dump() const;  // available to testing only
    void dumpCoin() const;
    void dumpAll() const;
    void dumpBase() const;
    void dumpHead() const;

    bool final() const {
        return fPtT.fT == 1;
    }

    SkOpAngle* fromAngle() const {
        return fFromAngle;
    }

    void initBase(SkOpSegment* parent, SkOpSpan* prev, double t, const SkPoint& pt);

    // Please keep this in sync with debugInsertCoinEnd()
    void insertCoinEnd(SkOpSpanBase* coin) {
        if (containsCoinEnd(coin)) {
            SkASSERT(coin->containsCoinEnd(this));
            return;
        }
        debugValidate();
        SkASSERT(this != coin);
        SkOpSpanBase* coinNext = coin->fCoinEnd;
        coin->fCoinEnd = this->fCoinEnd;
        this->fCoinEnd = coinNext;
        debugValidate();
    }

    void merge(SkOpSpan* span);
    void mergeMatches(SkOpSpanBase* opp);

    const SkOpSpan* prev() const {
        return fPrev;
    }

    SkOpSpan* prev() {
        return fPrev;
    }

    const SkPoint& pt() const {
        return fPtT.fPt;
    }

    const SkOpPtT* ptT() const {
        return &fPtT;
    }

    SkOpPtT* ptT() {
        return &fPtT;
    }

    SkOpSegment* segment() const {
        return fSegment;
    }

    void setAligned() {
        fAligned = true;
    }

    void setChased(bool chased) {
        fChased = chased;
    }

    void setFromAngle(SkOpAngle* angle) {
        fFromAngle = angle;
    }

    void setPrev(SkOpSpan* prev) {
        fPrev = prev;
    }

    bool simple() const {
        fPtT.debugValidate();
        return fPtT.next()->next() == &fPtT;
    }

    int spanAddsCount() const {
        return fSpanAdds;
    }

    const SkOpSpan* starter(const SkOpSpanBase* end) const {
        const SkOpSpanBase* result = t() < end->t() ? this : end;
        return result->upCast();
    }

    SkOpSpan* starter(SkOpSpanBase* end) {
        SkASSERT(this->segment() == end->segment());
        SkOpSpanBase* result = t() < end->t() ? this : end;
        return result->upCast();
    }

    SkOpSpan* starter(SkOpSpanBase** endPtr) {
        SkOpSpanBase* end = *endPtr;
        SkASSERT(this->segment() == end->segment());
        SkOpSpanBase* result;
        if (t() < end->t()) {
            result = this;
        } else {
            result = end;
            *endPtr = this;
        }
        return result->upCast();
    }

    int step(const SkOpSpanBase* end) const {
        return t() < end->t() ? 1 : -1;
    }

    double t() const {
        return fPtT.fT;
    }

    void unaligned() {
        fAligned = false;
    }

    SkOpSpan* upCast() {
        SkASSERT(!final());
        return (SkOpSpan*) this;
    }

    const SkOpSpan* upCast() const {
        SkOPASSERT(!final());
        return (const SkOpSpan*) this;
    }

    SkOpSpan* upCastable() {
        return final() ? nullptr : upCast();
    }

    const SkOpSpan* upCastable() const {
        return final() ? nullptr : upCast();
    }

private:
    void alignInner();

protected:  // no direct access to internals to avoid treating a span base as a span
    SkOpPtT fPtT;  // list of points and t values associated with the start of this span
    SkOpSegment* fSegment;  // segment that contains this span
    SkOpSpanBase* fCoinEnd;  // linked list of coincident spans that end here (may point to itself)
    SkOpAngle* fFromAngle;  // points to next angle from span start to end
    SkOpSpan* fPrev;  // previous intersection point
    int fSpanAdds;  // number of times intersections have been added to span
    bool fAligned;
    bool fChased;  // set after span has been added to chase array
    SkDEBUGCODE(int fCount);  // number of pt/t pairs added
    SkDEBUGCODE(int fID);
    SkDEBUGCODE(bool fDebugDeleted);  // set when span was merged with another span
};

class SkOpSpan : public SkOpSpanBase {
public:
    bool alreadyAdded() const {
        if (fAlreadyAdded) {
            return true;
        }
        fAlreadyAdded = true;
        return false;
    }

    bool clearCoincident() {
        SkASSERT(!final());
        if (fCoincident == this) {
            return false;
        }
        fCoincident = this;
        return true;
    }

    int computeWindSum();
    bool containsCoincidence(const SkOpSegment* ) const;

    bool containsCoincidence(const SkOpSpan* coin) const {
        SkASSERT(this != coin);
        const SkOpSpan* next = this;
        while ((next = next->fCoincident) != this) {
            if (next == coin) {
                return true;
            }
        }
        return false;
    }

    bool debugCoinLoopCheck() const;
#if DEBUG_COIN
    void debugInsertCoincidence(SkPathOpsDebug::GlitchLog* , const SkOpSpan* ) const;
    void debugInsertCoincidence(SkPathOpsDebug::GlitchLog* ,
                                const SkOpSegment* , bool flipped, bool ordered) const;
#endif
    void dumpCoin() const;
    bool dumpSpan() const;

    bool done() const {
        SkASSERT(!final());
        return fDone;
    }

    void init(SkOpSegment* parent, SkOpSpan* prev, double t, const SkPoint& pt);
    bool insertCoincidence(const SkOpSegment* , bool flipped, bool ordered);

    // Please keep this in sync with debugInsertCoincidence()
    void insertCoincidence(SkOpSpan* coin) {
        if (containsCoincidence(coin)) {
            SkASSERT(coin->containsCoincidence(this));
            return;
        }
        debugValidate();
        SkASSERT(this != coin);
        SkOpSpan* coinNext = coin->fCoincident;
        coin->fCoincident = this->fCoincident;
        this->fCoincident = coinNext;
        debugValidate();
    }

    bool isCanceled() const {
        SkASSERT(!final());
        return fWindValue == 0 && fOppValue == 0;
    }

    bool isCoincident() const {
        SkASSERT(!final());
        return fCoincident != this;
    }

    SkOpSpanBase* next() const {
        SkASSERT(!final());
        return fNext;
    }

    int oppSum() const {
        SkASSERT(!final());
        return fOppSum;
    }

    int oppValue() const {
        SkASSERT(!final());
        return fOppValue;
    }

    void release(const SkOpPtT* );

    SkOpPtT* setCoinStart(SkOpSpan* oldCoinStart, SkOpSegment* oppSegment);

    void setDone(bool done) {
        SkASSERT(!final());
        fDone = done;
    }

    void setNext(SkOpSpanBase* nextT) {
        SkASSERT(!final());
        fNext = nextT;
    }

    void setOppSum(int oppSum);

    void setOppValue(int oppValue) {
        SkASSERT(!final());
        SkASSERT(fOppSum == SK_MinS32);
        SkOPASSERT(!oppValue || !fDone);
        fOppValue = oppValue;
    }

    void setToAngle(SkOpAngle* angle) {
        SkASSERT(!final());
        fToAngle = angle;
    }

    void setWindSum(int windSum);

    void setWindValue(int windValue) {
        SkASSERT(!final());
        SkASSERT(windValue >= 0);
        SkASSERT(fWindSum == SK_MinS32);
        SkOPASSERT(!windValue || !fDone);
        fWindValue = windValue;
    }

    bool sortableTop(SkOpContour* );

    SkOpAngle* toAngle() const {
        SkASSERT(!final());
        return fToAngle;
    }

    int windSum() const {
        SkASSERT(!final());
        return fWindSum;
    }

    int windValue() const {
        SkOPASSERT(!final());
        return fWindValue;
    }

private:  // no direct access to internals to avoid treating a span base as a span
    SkOpSpan* fCoincident;  // linked list of spans coincident with this one (may point to itself)
    SkOpAngle* fToAngle;  // points to next angle from span start to end
    SkOpSpanBase* fNext;  // next intersection point
    int fWindSum;  // accumulated from contours surrounding this one.
    int fOppSum;  // for binary operators: the opposite winding sum
    int fWindValue;  // 0 == canceled; 1 == normal; >1 == coincident
    int fOppValue;  // normally 0 -- when binary coincident edges combine, opp value goes here
    int fTopTTry; // specifies direction and t value to try next
    bool fDone;  // if set, this span to next higher T has been processed
    mutable bool fAlreadyAdded;
};

#endif
