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

#include "include/core/SkPoint.h"
#include "include/core/SkTypes.h"
#include "include/private/SkDebug.h"
#include "include/private/SkMalloc.h"
#include "src/core/SkArenaAlloc.h"
#include "src/pathops/SkPathOpsCubic.h"
#include "src/pathops/SkPathOpsDebug.h"
#include "src/pathops/SkPathOpsPoint.h"
#include "src/pathops/SkPathOpsTCurve.h"

class SkIntersections;
class SkOpGlobalState;
struct SkDConic;
struct SkDLine;
struct SkDQuad;
struct SkDRect;

struct SkDQuadPair {
    const SkDQuad& first() const { return (const SkDQuad&) pts[0]; }
    const SkDQuad& second() const { return (const SkDQuad&) pts[2]; }
    SkDPoint pts[5];
};

struct SkDQuad {
    static const int kPointCount = 3;
    static const int kPointLast = kPointCount - 1;
    static const int kMaxIntersections = 4;

    SkDPoint fPts[kPointCount];

    bool collapsed() const {
        return fPts[0].approximatelyEqual(fPts[1]) && fPts[0].approximatelyEqual(fPts[2]);
    }

    bool controlsInside() const {
        SkDVector v01 = fPts[0] - fPts[1];
        SkDVector v02 = fPts[0] - fPts[2];
        SkDVector v12 = fPts[1] - fPts[2];
        return v02.dot(v01) > 0 && v02.dot(v12) > 0;
    }

    void debugInit() {
        sk_bzero(fPts, sizeof(fPts));
    }

    void debugSet(const SkDPoint* pts);

    SkDQuad flip() const {
        SkDQuad result = {{fPts[2], fPts[1], fPts[0]}  SkDEBUGPARAMS(fDebugGlobalState) };
        return result;
    }

    static bool IsConic() { return false; }

    const SkDQuad& set(const SkPoint pts[kPointCount]
            SkDEBUGPARAMS(SkOpGlobalState* state = nullptr)) {
        fPts[0] = pts[0];
        fPts[1] = pts[1];
        fPts[2] = pts[2];
        SkDEBUGCODE(fDebugGlobalState = state);
        return *this;
    }

    const SkDPoint& operator[](int n) const { SkASSERT(n >= 0 && n < kPointCount); return fPts[n]; }
    SkDPoint& operator[](int n) { SkASSERT(n >= 0 && n < kPointCount); return fPts[n]; }

    static int AddValidTs(double s[], int realRoots, double* t);
    void align(int endIndex, SkDPoint* dstPt) const;
    SkDQuadPair chopAt(double t) const;
    SkDVector dxdyAtT(double t) const;
    static int FindExtrema(const double src[], double tValue[1]);

#ifdef SK_DEBUG
    SkOpGlobalState* globalState() const { return fDebugGlobalState; }
#endif

    /**
     *  Return the number of valid roots (0 < root < 1) for this cubic intersecting the
     *  specified horizontal line.
     */
    int horizontalIntersect(double yIntercept, double roots[2]) const;

    bool hullIntersects(const SkDQuad& , bool* isLinear) const;
    bool hullIntersects(const SkDConic& , bool* isLinear) const;
    bool hullIntersects(const SkDCubic& , bool* isLinear) const;
    bool isLinear(int startIndex, int endIndex) const;
    static int maxIntersections() { return kMaxIntersections; }
    bool monotonicInX() const;
    bool monotonicInY() const;
    void otherPts(int oddMan, const SkDPoint* endPt[2]) const;
    static int pointCount() { return kPointCount; }
    static int pointLast() { return kPointLast; }
    SkDPoint ptAtT(double t) const;
    static int RootsReal(double A, double B, double C, double t[2]);
    static int RootsValidT(const double A, const double B, const double C, double s[2]);
    static void SetABC(const double* quad, double* a, double* b, double* c);
    SkDQuad subDivide(double t1, double t2) const;
    void subDivide(double t1, double t2, SkDQuad* quad) const { *quad = this->subDivide(t1, t2); }

    static SkDQuad SubDivide(const SkPoint a[kPointCount], double t1, double t2) {
        SkDQuad quad;
        quad.set(a);
        return quad.subDivide(t1, t2);
    }
    SkDPoint subDivide(const SkDPoint& a, const SkDPoint& c, double t1, double t2) const;
    static SkDPoint SubDivide(const SkPoint pts[kPointCount], const SkDPoint& a, const SkDPoint& c,
                              double t1, double t2) {
        SkDQuad quad;
        quad.set(pts);
        return quad.subDivide(a, c, t1, t2);
    }

    /**
     *  Return the number of valid roots (0 < root < 1) for this cubic intersecting the
     *  specified vertical line.
     */
    int verticalIntersect(double xIntercept, double roots[2]) const;

    SkDCubic debugToCubic() const;
    // utilities callable by the user from the debugger when the implementation code is linked in
    void dump() const;
    void dumpID(int id) const;
    void dumpInner() const;

    SkDEBUGCODE(SkOpGlobalState* fDebugGlobalState;)
};


class SkTQuad : public SkTCurve {
public:
    SkDQuad fQuad;

    SkTQuad() {}

    SkTQuad(const SkDQuad& q)
        : fQuad(q) {
    }

    ~SkTQuad() override {}

    const SkDPoint& operator[](int n) const override { return fQuad[n]; }
    SkDPoint& operator[](int n) override { return fQuad[n]; }

    bool collapsed() const override { return fQuad.collapsed(); }
    bool controlsInside() const override { return fQuad.controlsInside(); }
    void debugInit() override { return fQuad.debugInit(); }
#if DEBUG_T_SECT
    void dumpID(int id) const override { return fQuad.dumpID(id); }
#endif
    SkDVector dxdyAtT(double t) const override { return fQuad.dxdyAtT(t); }
#ifdef SK_DEBUG
    SkOpGlobalState* globalState() const override { return fQuad.globalState(); }
#endif

    bool hullIntersects(const SkDQuad& quad, bool* isLinear) const override {
        return quad.hullIntersects(fQuad, isLinear);
    }

    bool hullIntersects(const SkDConic& conic, bool* isLinear) const override;
    bool hullIntersects(const SkDCubic& cubic, bool* isLinear) const override;

    bool hullIntersects(const SkTCurve& curve, bool* isLinear) const override {
        return curve.hullIntersects(fQuad, isLinear);
    }

    int intersectRay(SkIntersections* i, const SkDLine& line) const override;
    bool IsConic() const override { return false; }
    SkTCurve* make(SkArenaAlloc& heap) const override { return heap.make<SkTQuad>(); }

    int maxIntersections() const override { return SkDQuad::kMaxIntersections; }

    void otherPts(int oddMan, const SkDPoint* endPt[2]) const override {
        fQuad.otherPts(oddMan, endPt);
    }

    int pointCount() const override { return SkDQuad::kPointCount; }
    int pointLast() const override { return SkDQuad::kPointLast; }
    SkDPoint ptAtT(double t) const override { return fQuad.ptAtT(t); }
    void setBounds(SkDRect* ) const override;

    void subDivide(double t1, double t2, SkTCurve* curve) const override {
        ((SkTQuad*) curve)->fQuad = fQuad.subDivide(t1, t2);
    }
};

#endif
