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

#ifndef skgpu_BufferWriter_DEFINED
#define skgpu_BufferWriter_DEFINED

#include "include/core/SkRect.h"
#include "include/private/SkColorData.h"
#include "include/private/SkNx.h"
#include "include/private/SkTemplates.h"
#include <type_traits>

namespace skgpu {

struct BufferWriter {
public:
    // Marks a read-only position in the underlying buffer
    struct Mark {
    public:
        Mark() : Mark(nullptr) {}
        Mark(void* ptr, size_t offset = 0)
                : fMark(reinterpret_cast<uintptr_t>(ptr) + offset) {
            SkASSERT(ptr || offset == 0);
        }

        bool operator< (const Mark& o) const { return fMark <  o.fMark; }
        bool operator<=(const Mark& o) const { return fMark <= o.fMark; }
        bool operator==(const Mark& o) const { return fMark == o.fMark; }
        bool operator!=(const Mark& o) const { return fMark != o.fMark; }
        bool operator>=(const Mark& o) const { return fMark >= o.fMark; }
        bool operator> (const Mark& o) const { return fMark >  o.fMark; }

        ptrdiff_t operator-(const Mark& o) const { return fMark - o.fMark; }

        explicit operator bool() const { return *this != Mark(); }
    private:
        uintptr_t fMark;
    };

    explicit operator bool() const { return fPtr != nullptr; }

    Mark mark(size_t offset=0) const {
        this->validate(offset);
        return Mark(fPtr, offset);
    }

protected:
    BufferWriter() = default;
    BufferWriter(void* ptr, size_t size) : fPtr(ptr) {
        SkDEBUGCODE(fEnd = Mark(ptr, ptr ? size : 0);)
    }
    BufferWriter(void* ptr, Mark end = {}) : fPtr(ptr) {
        SkDEBUGCODE(fEnd = end;)
    }

    BufferWriter& operator=(const BufferWriter&) = delete;
    BufferWriter& operator=(BufferWriter&& that) {
        fPtr = that.fPtr;
        that.fPtr = nullptr;
        SkDEBUGCODE(fEnd = that.fEnd;)
        SkDEBUGCODE(that.fEnd = Mark();)
        return *this;
    }

    // makeOffset effectively splits the current writer from {fPtr, fEnd} into {fPtr, p} and
    // a new writer {p, fEnd}. The same data range is accessible, but each byte can only be
    // set by a single writer. Automatically validates that there is enough bytes remaining in this
    // writer to do such a split.
    //
    // This splitting and validation means that providers of BufferWriters to callers can easily
    // and correctly track everything in a single BufferWriter field and use
    //    return std::exchange(fCurrWriter, fCurrWriter.makeOffset(requestedBytes));
    // This exposes the current writer position to the caller and sets the provider's new current
    // position to be just after the requested bytes.
    //
    // Templated so that it can create subclasses directly.
    template<typename W>
    W makeOffset(size_t offsetInBytes) const {
        this->validate(offsetInBytes);
        void* p = SkTAddOffset<void>(fPtr, offsetInBytes);
        Mark end{SkDEBUGCODE(fEnd)};
        SkDEBUGCODE(fEnd = Mark(p);)
        return W{p, end};
    }

    void validate(size_t bytesToWrite) const {
        // If the buffer writer had an end marked, make sure we're not crossing it.
        // Ideally, all creators of BufferWriters mark the end, but a lot of legacy code is not set
        // up to easily do this.
        SkASSERT(fPtr || bytesToWrite == 0);
        SkASSERT(!fEnd || Mark(fPtr, bytesToWrite) <= fEnd);
    }

protected:
    void* fPtr = nullptr;
    SkDEBUGCODE(mutable Mark fEnd = {};)
};

/**
 * Helper for writing vertex data to a buffer. Usage:
 *  VertexWriter vertices{target->makeVertexSpace(...)};
 *  vertices << A0 << B0 << C0 << ...;
 *  vertices << A1 << B1 << C1 << ...;
 *
 * Each value must be POD (plain old data), or have a specialization of the "<<" operator.
 */
struct VertexWriter : public BufferWriter {
    inline constexpr static uint32_t kIEEE_32_infinity = 0x7f800000;

    VertexWriter() = default;
    // DEPRECATED: Prefer specifying the size of the buffer being written to as well
    explicit VertexWriter(void* ptr) : BufferWriter(ptr, Mark()) {}

    VertexWriter(void* ptr, size_t size) : BufferWriter(ptr, size) {}
    VertexWriter(void* ptr, Mark end) : BufferWriter(ptr, end) {}

    VertexWriter(const VertexWriter&) = delete;
    VertexWriter(VertexWriter&& that) { *this = std::move(that); }

    VertexWriter& operator=(const VertexWriter&) = delete;
    VertexWriter& operator=(VertexWriter&& that) {
        BufferWriter::operator=(std::move(that));
        return *this;
    }

    VertexWriter makeOffset(size_t offsetInBytes) const {
        return this->BufferWriter::makeOffset<VertexWriter>(offsetInBytes);
    }

    template <typename T>
    struct Conditional {
        bool fCondition;
        T fValue;
    };

    template <typename T>
    static Conditional<T> If(bool condition, const T& value) {
        return {condition, value};
    }

    template <typename T>
    struct Skip {};

    template<typename T>
    struct ArrayDesc {
        const T* fArray;
        int fCount;
    };

    template <typename T>
    static ArrayDesc<T> Array(const T* array, int count) {
        return {array, count};
    }

    template<int kCount, typename T>
    struct RepeatDesc {
        const T& fVal;
    };

    template <int kCount, typename T>
    static RepeatDesc<kCount, T> Repeat(const T& val) {
        return {val};
    }

    /**
     * Specialized utilities for writing a four-vertices, with some data being replicated at each
     * vertex, and other data being the appropriate 2-components from an SkRect to construct a
     * triangle strip.
     *
     * - Four sets of data will be written
     *
     * - For any arguments where is_quad<Type>::value is true, a unique point will be written at
     *   each vertex. To make a custom type be emitted as a quad, declare:
     *
     *       template<> struct VertexWriter::is_quad<MyQuadClass> : std::true_type {};
     *
     *   and define:
     *
     *       MyQuadClass::writeVertex(int cornerIdx, VertexWriter&) const { ... }
     *
     * - For any arguments where is_quad<Type>::value is false, its value will be replicated at each
     *   vertex.
     */
    template <typename T>
    struct is_quad : std::false_type {};

    template <typename T>
    struct TriStrip {
        void writeVertex(int cornerIdx, VertexWriter& w) const {
            switch (cornerIdx) {
                case 0: w << l << t; return;
                case 1: w << l << b; return;
                case 2: w << r << t; return;
                case 3: w << r << b; return;
            }
            SkUNREACHABLE;
        }
        T l, t, r, b;
    };

    static TriStrip<float> TriStripFromRect(const SkRect& r) {
        return { r.fLeft, r.fTop, r.fRight, r.fBottom };
    }

    static TriStrip<uint16_t> TriStripFromUVs(const std::array<uint16_t, 4>& rect) {
        return { rect[0], rect[1], rect[2], rect[3] };
    }

    template <typename T>
    struct TriFan {
        void writeVertex(int cornerIdx, VertexWriter& w) const {
            switch (cornerIdx) {
                case 0: w << l << t; return;
                case 1: w << l << b; return;
                case 2: w << r << b; return;
                case 3: w << r << t; return;
            }
            SkUNREACHABLE;
        }
        T l, t, r, b;
    };

    static TriFan<float> TriFanFromRect(const SkRect& r) {
        return { r.fLeft, r.fTop, r.fRight, r.fBottom };
    }

    template <typename... Args>
    void writeQuad(const Args&... remainder) {
        this->writeQuadVertex<0>(remainder...);
        this->writeQuadVertex<1>(remainder...);
        this->writeQuadVertex<2>(remainder...);
        this->writeQuadVertex<3>(remainder...);
    }

private:
    template <int kCornerIdx, typename T, typename... Args>
    std::enable_if_t<!is_quad<T>::value, void> writeQuadVertex(const T& val,
                                                               const Args&... remainder) {
        *this << val;  // Non-quads duplicate their value.
        this->writeQuadVertex<kCornerIdx>(remainder...);
    }

    template <int kCornerIdx, typename Q, typename... Args>
    std::enable_if_t<is_quad<Q>::value, void> writeQuadVertex(const Q& quad,
                                                              const Args&... remainder) {
        quad.writeVertex(kCornerIdx, *this);  // Quads emit a different corner each time.
        this->writeQuadVertex<kCornerIdx>(remainder...);
    }

    template <int kCornerIdx>
    void writeQuadVertex() {}

    template <typename T>
    friend VertexWriter& operator<<(VertexWriter&, const T&);

    template <typename T>
    friend VertexWriter& operator<<(VertexWriter&, const ArrayDesc<T>&);
};

template <typename T>
inline VertexWriter& operator<<(VertexWriter& w, const T& val) {
    static_assert(std::is_pod<T>::value, "");
    w.validate(sizeof(T));
    memcpy(w.fPtr, &val, sizeof(T));
    w = w.makeOffset(sizeof(T));
    return w;
}

template <typename T>
inline VertexWriter& operator<<(VertexWriter& w, const VertexWriter::Conditional<T>& val) {
    static_assert(std::is_pod<T>::value, "");
    if (val.fCondition) {
        w << val.fValue;
    }
    return w;
}

template <typename T>
inline VertexWriter& operator<<(VertexWriter& w, const VertexWriter::Skip<T>& val) {
    w = w.makeOffset(sizeof(T));
    return w;
}

template <typename T>
inline VertexWriter& operator<<(VertexWriter& w, const VertexWriter::ArrayDesc<T>& array) {
    static_assert(std::is_pod<T>::value, "");
    w.validate(array.fCount * sizeof(T));
    memcpy(w.fPtr, array.fArray, array.fCount * sizeof(T));
    w = w.makeOffset(sizeof(T) * array.fCount);
    return w;
}

template <int kCount, typename T>
inline VertexWriter& operator<<(VertexWriter& w, const VertexWriter::RepeatDesc<kCount,T>& repeat) {
    for (int i = 0; i < kCount; ++i) {
        w << repeat.fVal;
    }
    return w;
}

template <>
SK_MAYBE_UNUSED inline VertexWriter& operator<<(VertexWriter& w, const Sk4f& vector) {
    w.validate(sizeof(vector));
    vector.store(w.fPtr);
    w = w.makeOffset(sizeof(vector));
    return w;
}

// Allow r-value/temporary writers to be appended to
template <typename T>
inline VertexWriter& operator<<(VertexWriter&& w, const T& val) { return w << val; }

template <typename T>
struct VertexWriter::is_quad<VertexWriter::TriStrip<T>> : std::true_type {};

template <typename T>
struct VertexWriter::is_quad<VertexWriter::TriFan<T>> : std::true_type {};

/**
 * VertexColor is a helper for writing colors to a vertex buffer. It outputs either four bytes or
 * or four float32 channels, depending on the wideColor parameter. Note that the GP needs to have
 * been constructed with the correct attribute type for colors, to match the usage here.
 */
class VertexColor {
public:
    VertexColor() = default;

    explicit VertexColor(const SkPMColor4f& color, bool wideColor) {
        this->set(color, wideColor);
    }

    void set(const SkPMColor4f& color, bool wideColor) {
        if (wideColor) {
            memcpy(fColor, color.vec(), sizeof(fColor));
        } else {
            fColor[0] = color.toBytes_RGBA();
        }
        fWideColor = wideColor;
    }

    size_t size() const { return fWideColor ? 16 : 4; }

private:
    template <typename T>
    friend VertexWriter& operator<<(VertexWriter&, const T&);

    uint32_t fColor[4];
    bool     fWideColor;
};

template <>
SK_MAYBE_UNUSED inline VertexWriter& operator<<(VertexWriter& w, const VertexColor& color) {
    w << color.fColor[0];
    if (color.fWideColor) {
        w << color.fColor[1]
          << color.fColor[2]
          << color.fColor[3];
    }
    return w;
}

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

struct IndexWriter : public BufferWriter {
    IndexWriter() = default;

    IndexWriter(void* ptr, size_t size) : BufferWriter(ptr, size) {}
    IndexWriter(void* ptr, Mark end) : BufferWriter(ptr, end) {}

    IndexWriter(const IndexWriter&) = delete;
    IndexWriter(IndexWriter&& that) { *this = std::move(that); }

    IndexWriter& operator=(const IndexWriter&) = delete;
    IndexWriter& operator=(IndexWriter&& that) {
        BufferWriter::operator=(std::move(that));
        return *this;
    }

    IndexWriter makeOffset(int numIndices) const {
        return this->BufferWriter::makeOffset<IndexWriter>(numIndices * sizeof(uint16_t));
    }

    void writeArray(const uint16_t* array, int count) {
        size_t arraySize = count * sizeof(uint16_t);
        this->validate(arraySize);
        memcpy(fPtr, array, arraySize);
        fPtr = SkTAddOffset<void>(fPtr, arraySize);
    }

    friend IndexWriter& operator<<(IndexWriter& w, uint16_t val);
};

inline IndexWriter& operator<<(IndexWriter& w, uint16_t val) {
    w.validate(sizeof(uint16_t));
    memcpy(w.fPtr, &val, sizeof(uint16_t));
    w = w.makeOffset(1);
    return w;
}

inline IndexWriter& operator<<(IndexWriter& w, int val) { return (w << SkTo<uint16_t>(val)); }

template<typename T>
inline IndexWriter& operator<<(IndexWriter&& w, const T& val) { return w << val; }

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

struct UniformWriter : public BufferWriter {
    UniformWriter() = default;

    UniformWriter(void* ptr, size_t size) : BufferWriter(ptr, size) {}
    UniformWriter(void* ptr, Mark end) : BufferWriter(ptr, end) {}

    UniformWriter(const UniformWriter&) = delete;
    UniformWriter(UniformWriter&& that) { *this = std::move(that); }

    UniformWriter& operator=(const UniformWriter&) = delete;
    UniformWriter& operator=(UniformWriter&& that) {
        BufferWriter::operator=(std::move(that));
        return *this;
    }

    void write(const void* src, size_t bytes) {
        this->validate(bytes);
        memcpy(fPtr, src, bytes);
        fPtr = SkTAddOffset<void>(fPtr, bytes);
    }
};

}  // namespace skgpu

#endif // skgpu_BufferWriter_DEFINED
