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

#ifndef SkXform_DEFINED
#define SkXform_DEFINED

#include "include/core/SkClipOp.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPath.h"
#include "include/core/SkRRect.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"

#include "include/private/SkTDArray.h"

class XformResolver {
public:
    virtual ~XformResolver() {}

    virtual void concat(const SkMatrix&) = 0;
    virtual void clipRect(const SkRect&, SkClipOp) = 0;
    virtual void clipRRect(const SkRRect&, SkClipOp) = 0;
    virtual void clipPath(const SkPath&, SkClipOp) = 0;
};

class ClipCache : public SkRefCnt {
public:
    ClipCache() {}
};

class Xform : public SkRefCnt {
public:
    typedef uint32_t GenID;

    Xform* parent() const { return fParent.get(); }
    void setParent(sk_sp<Xform> p);

    void visit(XformResolver* resolver);

    GenID genID() const { return fGenID; }

    bool isCached() const { return !!fClip; }
    void invalidateCaches();

    const SkMatrix& ctm() const { return fCTM; }
    ClipCache* clip() const { return fClip.get(); }

    void setCache(const SkMatrix&, sk_sp<ClipCache>);

protected:
    Xform(sk_sp<Xform> parent = nullptr) {
        if (parent) {
            this->setParent(std::move(parent));
        }
    }

    virtual void onVisit(XformResolver*) {}

private:
    sk_sp<Xform> fParent;

    // unowned bare pointers
    SkTDArray<Xform*> fChildren;

    // cache
    SkMatrix         fCTM;
    sk_sp<ClipCache> fClip;

    uint32_t fGenID = 0;

    static GenID NextGenID();

    void internalInvalidateCaches() { fClip = nullptr; }
    void internalAddChild(Xform*);
    void internalRemoveChild(Xform*);

#ifdef SK_DEBUG
    void debugValidate() const;
#else
    void debugValidate() const {}
#endif
};

///////////////////////////////////////////////////////////////////////////////////////////////

class MatrixXF : public Xform {
public:
    static sk_sp<MatrixXF> Make(sk_sp<Xform> parent = nullptr) {
        return sk_sp<MatrixXF>(new MatrixXF(std::move(parent)));
    }

    MatrixXF(sk_sp<Xform> parent) : Xform(std::move(parent)) {
        fLocalMatrix.reset();
    }

    void setLocalMatrix(const SkMatrix& m) {
        fLocalMatrix = m;
    }
    void setTranslate(SkScalar sx, SkScalar sy) {
        fLocalMatrix.setTranslate(sx, sy);
    }
    void setScale(SkScalar sx, SkScalar sy) {
        fLocalMatrix.setScale(sx, sy);
    }
    void setRotate(SkScalar degrees) {
        fLocalMatrix.setRotate(degrees);
    }

protected:
    void onVisit(XformResolver* resolver) override;

private:
    SkMatrix fLocalMatrix;
};

class ClipXF : public Xform {
public:
    ClipXF(sk_sp<Xform> parent = nullptr) : Xform(std::move(parent)) {}
    ClipXF(sk_sp<Xform> parent, const SkRect& r, SkClipOp op = SkClipOp::kIntersect)
        : Xform(std::move(parent))
        , fRect(r)
        , fOp(op)
    {}

    void setRect(const SkRect& r, SkClipOp op = SkClipOp::kIntersect) {
        fRect = r;
        fOp = op;
    }

protected:
    void onVisit(XformResolver* resolver) override;

private:
    SkRect      fRect;
    SkClipOp    fOp;
};

#endif
