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

#ifndef SkMatrix44_DEFINED
#define SkMatrix44_DEFINED

#include "include/core/SkMatrix.h"
#include "include/core/SkScalar.h"

#include <atomic>
#include <cstring>

// This entire file is DEPRECATED, and will be removed at some point.
// SkCanvas has full support for 4x4 matrices using SkM44

// DEPRECATED
struct SkVector4 {
    SkScalar fData[4];

    SkVector4() {
        this->set(0, 0, 0, 1);
    }
    SkVector4(const SkVector4& src) {
        memcpy(fData, src.fData, sizeof(fData));
    }
    SkVector4(SkScalar x, SkScalar y, SkScalar z, SkScalar w = SK_Scalar1) {
        fData[0] = x;
        fData[1] = y;
        fData[2] = z;
        fData[3] = w;
    }

    SkVector4& operator=(const SkVector4& src) {
        memcpy(fData, src.fData, sizeof(fData));
        return *this;
    }

    bool operator==(const SkVector4& v) const {
        return fData[0] == v.fData[0] && fData[1] == v.fData[1] &&
               fData[2] == v.fData[2] && fData[3] == v.fData[3];
    }
    bool operator!=(const SkVector4& v) const { return !(*this == v); }
    bool equals(SkScalar x, SkScalar y, SkScalar z, SkScalar w = SK_Scalar1) {
        return fData[0] == x && fData[1] == y &&
               fData[2] == z && fData[3] == w;
    }

    void set(SkScalar x, SkScalar y, SkScalar z, SkScalar w = SK_Scalar1) {
        fData[0] = x;
        fData[1] = y;
        fData[2] = z;
        fData[3] = w;
    }
};

// DEPRECATED
class SK_API SkMatrix44 {
public:

    enum Uninitialized_Constructor {
        kUninitialized_Constructor
    };
    enum Identity_Constructor {
        kIdentity_Constructor
    };
    enum NaN_Constructor {
        kNaN_Constructor
    };

    SkMatrix44(Uninitialized_Constructor) {}  // ironically, cannot be constexpr

    constexpr SkMatrix44(Identity_Constructor)
        : fMat{{ 1, 0, 0, 0, },
               { 0, 1, 0, 0, },
               { 0, 0, 1, 0, },
               { 0, 0, 0, 1, }}
        , fTypeMask(kIdentity_Mask) {}

    SkMatrix44(NaN_Constructor)
        : fMat{{ SK_ScalarNaN, SK_ScalarNaN, SK_ScalarNaN, SK_ScalarNaN },
               { SK_ScalarNaN, SK_ScalarNaN, SK_ScalarNaN, SK_ScalarNaN },
               { SK_ScalarNaN, SK_ScalarNaN, SK_ScalarNaN, SK_ScalarNaN },
               { SK_ScalarNaN, SK_ScalarNaN, SK_ScalarNaN, SK_ScalarNaN }}
        , fTypeMask(kTranslate_Mask | kScale_Mask | kAffine_Mask | kPerspective_Mask) {}

    constexpr SkMatrix44() : SkMatrix44{kIdentity_Constructor} {}

    SkMatrix44(const SkMatrix44& src) = default;

    SkMatrix44& operator=(const SkMatrix44& src) = default;

    SkMatrix44(const SkMatrix44& a, const SkMatrix44& b) {
        this->setConcat(a, b);
    }

    bool operator==(const SkMatrix44& other) const;
    bool operator!=(const SkMatrix44& other) const {
        return !(other == *this);
    }

    /* When converting from SkMatrix44 to SkMatrix, the third row and
     * column is dropped.  When converting from SkMatrix to SkMatrix44
     * the third row and column remain as identity:
     * [ a b c ]      [ a b 0 c ]
     * [ d e f ]  ->  [ d e 0 f ]
     * [ g h i ]      [ 0 0 1 0 ]
     *                [ g h 0 i ]
     */
    SkMatrix44(const SkMatrix&);
    SkMatrix44& operator=(const SkMatrix& src);

    // TODO: make this explicit (will need to guard that change to update chrome, etc.
#ifndef SK_SUPPORT_LEGACY_IMPLICIT_CONVERSION_MATRIX44
    explicit
#endif
    operator SkMatrix() const;

    /**
     *  Return a reference to a const identity matrix
     */
    static const SkMatrix44& I();

    using TypeMask = uint8_t;
    enum : TypeMask {
        kIdentity_Mask = 0,
        kTranslate_Mask = 1 << 0,    //!< set if the matrix has translation
        kScale_Mask = 1 << 1,        //!< set if the matrix has any scale != 1
        kAffine_Mask = 1 << 2,       //!< set if the matrix skews or rotates
        kPerspective_Mask = 1 << 3,  //!< set if the matrix is in perspective
    };

    /**
     *  Returns a bitfield describing the transformations the matrix may
     *  perform. The bitfield is computed conservatively, so it may include
     *  false positives. For example, when kPerspective_Mask is true, all
     *  other bits may be set to true even in the case of a pure perspective
     *  transform.
     */
    inline TypeMask getType() const { return fTypeMask; }

    /**
     *  Return true if the matrix is identity.
     */
    inline bool isIdentity() const {
        return kIdentity_Mask == this->getType();
    }

    /**
     *  Return true if the matrix contains translate or is identity.
     */
    inline bool isTranslate() const {
        return !(this->getType() & ~kTranslate_Mask);
    }

    /**
     *  Return true if the matrix only contains scale or translate or is identity.
     */
    inline bool isScaleTranslate() const {
        return !(this->getType() & ~(kScale_Mask | kTranslate_Mask));
    }

    /**
     *  Returns true if the matrix only contains scale or is identity.
     */
    inline bool isScale() const {
            return !(this->getType() & ~kScale_Mask);
    }

    inline bool hasPerspective() const {
        return SkToBool(this->getType() & kPerspective_Mask);
    }

    void setIdentity();
    inline void reset() { this->setIdentity();}

    /**
     *  get a value from the matrix. The row,col parameters work as follows:
     *  (0, 0)  scale-x
     *  (0, 3)  translate-x
     *  (3, 0)  perspective-x
     */
    inline SkScalar get(int row, int col) const {
        SkASSERT((unsigned)row <= 3);
        SkASSERT((unsigned)col <= 3);
        return fMat[col][row];
    }

    /**
     *  set a value in the matrix. The row,col parameters work as follows:
     *  (0, 0)  scale-x
     *  (0, 3)  translate-x
     *  (3, 0)  perspective-x
     */
    inline void set(int row, int col, SkScalar value) {
        SkASSERT((unsigned)row <= 3);
        SkASSERT((unsigned)col <= 3);
        fMat[col][row] = value;
        this->recomputeTypeMask();
    }

    inline double getDouble(int row, int col) const {
        return double(this->get(row, col));
    }
    inline void setDouble(int row, int col, double value) {
        this->set(row, col, SkScalar(value));
    }
    inline float getFloat(int row, int col) const {
        return float(this->get(row, col));
    }
    inline void setFloat(int row, int col, float value) {
        this->set(row, col, value);
    }

    /** These methods allow one to efficiently read matrix entries into an
     *  array. The given array must have room for exactly 16 entries. Whenever
     *  possible, they will try to use memcpy rather than an entry-by-entry
     *  copy.
     *
     *  Col major indicates that consecutive elements of columns will be stored
     *  contiguously in memory.  Row major indicates that consecutive elements
     *  of rows will be stored contiguously in memory.
     */
    void asColMajorf(float[]) const;
    void asColMajord(double[]) const;
    void asRowMajorf(float[]) const;
    void asRowMajord(double[]) const;

    /** These methods allow one to efficiently set all matrix entries from an
     *  array. The given array must have room for exactly 16 entries. Whenever
     *  possible, they will try to use memcpy rather than an entry-by-entry
     *  copy.
     *
     *  Col major indicates that input memory will be treated as if consecutive
     *  elements of columns are stored contiguously in memory.  Row major
     *  indicates that input memory will be treated as if consecutive elements
     *  of rows are stored contiguously in memory.
     */
    void setColMajorf(const float[]);
    void setColMajord(const double[]);
    void setRowMajorf(const float[]);
    void setRowMajord(const double[]);

    void setColMajor(const SkScalar data[]) { this->setColMajorf(data); }
    void setRowMajor(const SkScalar data[]) { this->setRowMajorf(data); }

    /* This sets the top-left of the matrix and clears the translation and
     * perspective components (with [3][3] set to 1).  m_ij is interpreted
     * as the matrix entry at row = i, col = j. */
    void set3x3(SkScalar m_00, SkScalar m_10, SkScalar m_20,
                SkScalar m_01, SkScalar m_11, SkScalar m_21,
                SkScalar m_02, SkScalar m_12, SkScalar m_22);
    void set3x3RowMajorf(const float[]);

    void set4x4(SkScalar m_00, SkScalar m_10, SkScalar m_20, SkScalar m_30,
                SkScalar m_01, SkScalar m_11, SkScalar m_21, SkScalar m_31,
                SkScalar m_02, SkScalar m_12, SkScalar m_22, SkScalar m_32,
                SkScalar m_03, SkScalar m_13, SkScalar m_23, SkScalar m_33);

    SkMatrix44& setTranslate(SkScalar dx, SkScalar dy, SkScalar dz);
    SkMatrix44& preTranslate(SkScalar dx, SkScalar dy, SkScalar dz);
    SkMatrix44& postTranslate(SkScalar dx, SkScalar dy, SkScalar dz);

    SkMatrix44& setScale(SkScalar sx, SkScalar sy, SkScalar sz);
    SkMatrix44& preScale(SkScalar sx, SkScalar sy, SkScalar sz);
    SkMatrix44& postScale(SkScalar sx, SkScalar sy, SkScalar sz);

    inline SkMatrix44& setScale(SkScalar scale) {
        return this->setScale(scale, scale, scale);
    }
    inline SkMatrix44& preScale(SkScalar scale) {
        return this->preScale(scale, scale, scale);
    }
    inline SkMatrix44& postScale(SkScalar scale) {
        return this->postScale(scale, scale, scale);
    }

    void setRotateDegreesAbout(SkScalar x, SkScalar y, SkScalar z, SkScalar degrees) {
        this->setRotateAbout(x, y, z, degrees * SK_ScalarPI / 180);
    }

    /** Rotate about the vector [x,y,z]. If that vector is not unit-length,
        it will be automatically resized.
     */
    void setRotateAbout(SkScalar x, SkScalar y, SkScalar z, SkScalar radians);
    /** Rotate about the vector [x,y,z]. Does not check the length of the
        vector, assuming it is unit-length.
     */
    void setRotateAboutUnit(SkScalar x, SkScalar y, SkScalar z, SkScalar radians);

    void setConcat(const SkMatrix44& a, const SkMatrix44& b);
    inline void preConcat(const SkMatrix44& m) {
        this->setConcat(*this, m);
    }
    inline void postConcat(const SkMatrix44& m) {
        this->setConcat(m, *this);
    }

    friend SkMatrix44 operator*(const SkMatrix44& a, const SkMatrix44& b) {
        return SkMatrix44(a, b);
    }

    /** If this is invertible, return that in inverse and return true. If it is
        not invertible, return false and leave the inverse parameter in an
        unspecified state.
     */
    bool invert(SkMatrix44* inverse) const;

    /** Transpose this matrix in place. */
    void transpose();

    /** Apply the matrix to the src vector, returning the new vector in dst.
        It is legal for src and dst to point to the same memory.
     */
    void mapScalars(const SkScalar src[4], SkScalar dst[4]) const;
    inline void mapScalars(SkScalar vec[4]) const {
        this->mapScalars(vec, vec);
    }

    friend SkVector4 operator*(const SkMatrix44& m, const SkVector4& src) {
        SkVector4 dst;
        m.mapScalars(src.fData, dst.fData);
        return dst;
    }

    /**
     *  map an array of [x, y, 0, 1] through the matrix, returning an array
     *  of [x', y', z', w'].
     *
     *  @param src2     array of [x, y] pairs, with implied z=0 and w=1
     *  @param count    number of [x, y] pairs in src2
     *  @param dst4     array of [x', y', z', w'] quads as the output.
     */
    void map2(const float src2[], int count, float dst4[]) const;
    void map2(const double src2[], int count, double dst4[]) const;

    /** Returns true if transformating an axis-aligned square in 2d by this matrix
        will produce another 2d axis-aligned square; typically means the matrix
        is a scale with perhaps a 90-degree rotation. A 3d rotation through 90
        degrees into a perpendicular plane collapses a square to a line, but
        is still considered to be axis-aligned.

        By default, tolerates very slight error due to float imprecisions;
        a 90-degree rotation can still end up with 10^-17 of
        "non-axis-aligned" result.
     */
    bool preserves2dAxisAlignment(SkScalar epsilon = SK_ScalarNearlyZero) const;

    void dump() const;

    double determinant() const;

private:
    /* This is indexed by [col][row]. */
    SkScalar fMat[4][4];
    TypeMask fTypeMask;

    static constexpr int kAllPublic_Masks = 0xF;

    void as3x4RowMajorf(float[]) const;
    void set3x4RowMajorf(const float[]);

    SkScalar transX() const { return fMat[3][0]; }
    SkScalar transY() const { return fMat[3][1]; }
    SkScalar transZ() const { return fMat[3][2]; }

    SkScalar scaleX() const { return fMat[0][0]; }
    SkScalar scaleY() const { return fMat[1][1]; }
    SkScalar scaleZ() const { return fMat[2][2]; }

    SkScalar perspX() const { return fMat[0][3]; }
    SkScalar perspY() const { return fMat[1][3]; }
    SkScalar perspZ() const { return fMat[2][3]; }

    void recomputeTypeMask();

    inline void setTypeMask(TypeMask mask) {
        SkASSERT(0 == (~kAllPublic_Masks & mask));
        fTypeMask = mask;
    }

    inline const SkScalar* values() const { return &fMat[0][0]; }

    friend class SkColorSpace;
    friend class SkCanvas;
    friend class SkM44;
};

#endif
