/*
 * 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 SkIntersections_DEFINE
#define SkIntersections_DEFINE

#include "SkPathOpsCubic.h"
#include "SkPathOpsLine.h"
#include "SkPathOpsPoint.h"
#include "SkPathOpsQuad.h"

class SkIntersections {
public:
    SkIntersections()
        : fSwap(0)
#ifdef SK_DEBUG
        , fDepth(0)
#endif
    {
        sk_bzero(fPt, sizeof(fPt));
        sk_bzero(fT, sizeof(fT));
        sk_bzero(fIsCoincident, sizeof(fIsCoincident));
        reset();
    }

    class TArray {
    public:
        explicit TArray(const double ts[9]) : fTArray(ts) {}
        double operator[](int n) const {
            return fTArray[n];
        }
        const double* fTArray;
    };
    TArray operator[](int n) const { return TArray(fT[n]); }

    void set(const SkIntersections& i) {
        memcpy(fPt, i.fPt, sizeof(fPt));
        memcpy(fT, i.fT, sizeof(fT));
        memcpy(fIsCoincident, i.fIsCoincident, sizeof(fIsCoincident));
        fUsed = i.fUsed;
        fSwap = i.fSwap;
        SkDEBUGCODE(fDepth = i.fDepth);
    }

    int cubic(const SkPoint a[4]) {
        SkDCubic cubic;
        cubic.set(a);
        return intersect(cubic);
    }

    int cubicCubic(const SkPoint a[4], const SkPoint b[4]) {
        SkDCubic aCubic;
        aCubic.set(a);
        SkDCubic bCubic;
        bCubic.set(b);
        return intersect(aCubic, bCubic);
    }

    int cubicHorizontal(const SkPoint a[4], SkScalar left, SkScalar right, SkScalar y,
                        bool flipped) {
        SkDCubic cubic;
        cubic.set(a);
        return horizontal(cubic, left, right, y, flipped);
    }

    int cubicVertical(const SkPoint a[4], SkScalar top, SkScalar bottom, SkScalar x, bool flipped) {
        SkDCubic cubic;
        cubic.set(a);
        return vertical(cubic, top, bottom, x, flipped);
    }

    int cubicLine(const SkPoint a[4], const SkPoint b[2]) {
        SkDCubic cubic;
        cubic.set(a);
        SkDLine line;
        line.set(b);
        return intersect(cubic, line);
    }

    int cubicQuad(const SkPoint a[4], const SkPoint b[3]) {
        SkDCubic cubic;
        cubic.set(a);
        SkDQuad quad;
        quad.set(b);
        return intersect(cubic, quad);
    }

    int insertSwap(double one, double two, const SkDPoint& pt) {
        if (fSwap) {
            return insert(two, one, pt);
        } else {
            return insert(one, two, pt);
        }
    }

    bool isCoincident(int index) {
        return (fIsCoincident[0] & 1 << index) != 0;
    }

    int lineHorizontal(const SkPoint a[2], SkScalar left, SkScalar right, SkScalar y,
                       bool flipped) {
        SkDLine line;
        line.set(a);
        return horizontal(line, left, right, y, flipped);
    }

    int lineVertical(const SkPoint a[2], SkScalar top, SkScalar bottom, SkScalar x, bool flipped) {
        SkDLine line;
        line.set(a);
        return vertical(line, top, bottom, x, flipped);
    }

    int lineLine(const SkPoint a[2], const SkPoint b[2]) {
        SkDLine aLine, bLine;
        aLine.set(a);
        bLine.set(b);
        return intersect(aLine, bLine);
    }

    const SkDPoint& pt(int index) const {
        return fPt[index];
    }

    int quadHorizontal(const SkPoint a[3], SkScalar left, SkScalar right, SkScalar y,
                       bool flipped) {
        SkDQuad quad;
        quad.set(a);
        return horizontal(quad, left, right, y, flipped);
    }

    int quadVertical(const SkPoint a[3], SkScalar top, SkScalar bottom, SkScalar x, bool flipped) {
        SkDQuad quad;
        quad.set(a);
        return vertical(quad, top, bottom, x, flipped);
    }

    int quadLine(const SkPoint a[3], const SkPoint b[2]) {
        SkDQuad quad;
        quad.set(a);
        SkDLine line;
        line.set(b);
        return intersect(quad, line);
    }

    int quadQuad(const SkPoint a[3], const SkPoint b[3]) {
        SkDQuad aQuad;
        aQuad.set(a);
        SkDQuad bQuad;
        bQuad.set(b);
        return intersect(aQuad, bQuad);
    }

    int quadRay(const SkPoint pts[3], const SkDLine& line);
    void removeOne(int index);

    // leaves flip, swap alone
    void reset() {
        fUsed = 0;
    }

    void swap() {
        fSwap ^= true;
    }

    void swapPts();

    bool swapped() const {
        return fSwap;
    }

    int used() const {
        return fUsed;
    }

    void downDepth() {
        SkASSERT(--fDepth >= 0);
    }

    void upDepth() {
        SkASSERT(++fDepth < 16);
    }

    static double Axial(const SkDQuad& , const SkDPoint& , bool vertical);
    int coincidentUsed() const;
    int cubicRay(const SkPoint pts[4], const SkDLine& line);
    void flip();
    int horizontal(const SkDLine&, double y);
    int horizontal(const SkDLine&, double left, double right, double y);
    int horizontal(const SkDLine&, double left, double right, double y, bool flipped);
    int horizontal(const SkDQuad&, double left, double right, double y, bool flipped);
    int horizontal(const SkDQuad&, double left, double right, double y, double tRange[2]);
    int horizontal(const SkDCubic&, double y, double tRange[3]);
    int horizontal(const SkDCubic&, double left, double right, double y, bool flipped);
    int horizontal(const SkDCubic&, double left, double right, double y, double tRange[3]);
    // FIXME : does not respect swap
    int insert(double one, double two, const SkDPoint& pt);
    // start if index == 0 : end if index == 1
    void insertCoincident(double one, double two, const SkDPoint& pt);
    void insertCoincidentPair(double s1, double e1, double s2, double e2,
            const SkDPoint& startPt, const SkDPoint& endPt);
    int intersect(const SkDLine&, const SkDLine&);
    int intersect(const SkDQuad&, const SkDLine&);
    int intersect(const SkDQuad&, const SkDQuad&);
    int intersect(const SkDCubic&);  // return true if cubic self-intersects
    int intersect(const SkDCubic&, const SkDLine&);
    int intersect(const SkDCubic&, const SkDQuad&);
    int intersect(const SkDCubic&, const SkDCubic&);
    int intersectRay(const SkDCubic& , const SkDLine&);
    int intersectRay(const SkDQuad& , const SkDLine&);
    static SkDPoint Line(const SkDLine& , const SkDLine&);
    void offset(int base, double start, double end);
    void quickRemoveOne(int index, int replace);
    static bool Test(const SkDLine& , const SkDLine&);
    int vertical(const SkDLine&, double x);
    int vertical(const SkDLine&, double top, double bottom, double x, bool flipped);
    int vertical(const SkDQuad&, double top, double bottom, double x, bool flipped);
    int vertical(const SkDCubic&, double top, double bottom, double x, bool flipped);
    int verticalCubic(const SkPoint a[4], SkScalar top, SkScalar bottom, SkScalar x, bool flipped);
    int verticalLine(const SkPoint a[2], SkScalar top, SkScalar bottom, SkScalar x, bool flipped);
    int verticalQuad(const SkPoint a[3], SkScalar top, SkScalar bottom, SkScalar x, bool flipped);

    int depth() const {
#ifdef SK_DEBUG
        return fDepth;
#else
        return 0;
#endif
    }

private:
    int computePoints(const SkDLine& line, int used);
    // used by addCoincident to remove ordinary intersections in range
    void remove(double one, double two, const SkDPoint& startPt, const SkDPoint& endPt);

    SkDPoint fPt[9];
    double fT[2][9];
    uint16_t fIsCoincident[2];  // bit arrays, one bit set for each coincident T
    unsigned char fUsed;
    bool fSwap;
#ifdef SK_DEBUG
    int fDepth;
#endif
};

extern int (SkIntersections::*CurveRay[])(const SkPoint[], const SkDLine& );
extern int (SkIntersections::*CurveVertical[])(const SkPoint[], SkScalar top, SkScalar bottom,
            SkScalar x, bool flipped);

#endif
