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

#ifndef SkCombinationBuilder_DEFINED
#define SkCombinationBuilder_DEFINED

#include "include/core/SkTypes.h"

#ifdef SK_ENABLE_PRECOMPILE

#include <functional>
#include <memory>
#include <vector>
#include "include/core/SkBlendMode.h"
#include "include/core/SkSpan.h"
#include "include/core/SkTileMode.h"
#include "include/private/SkTArray.h"
#include "include/private/SkTHash.h"

class SkArenaAllocWithReset;
class SkCombinationBuilder;
class SkKeyContext;
class SkOption;
class SkPaintParamsKeyBuilder;
class SkShaderCodeDictionary;
class SkUniquePaintParamsID;

namespace skgpu::graphite {
class Context;
}

enum class SkShaderType : uint32_t {
    kSolidColor,

    kLinearGradient,
    kRadialGradient,
    kSweepGradient,
    kConicalGradient,

    kLocalMatrix,
    kImage,
    kBlendShader,
    kRuntimeShader,

    kLast          = kRuntimeShader
};

static constexpr int kSkShaderTypeCount = static_cast<int>(SkShaderType::kLast) + 1;

struct SkTileModePair {
    SkTileMode fX;
    SkTileMode fY;

    bool operator==(const SkTileModePair& other) const { return fX == other.fX && fY == other.fY; }
    bool operator!=(const SkTileModePair& other) const { return !(*this == other); }
};

// TODO: add SkShaderID and SkColorFilterID too
class SkBlenderID {
public:
    SkBlenderID() : fID(0) {}  // 0 is an invalid blender ID
    SkBlenderID(const SkBlenderID& src) : fID(src.fID) {}

    bool isValid() const { return fID > 0; }

    bool operator==(const SkBlenderID& other) const { return fID == other.fID; }

    SkBlenderID& operator=(const SkBlenderID& src) {
        fID = src.fID;
        return *this;
    }

private:
    friend class SkShaderCodeDictionary;     // for ctor and asUInt access
    friend class SkCombinationBuilder;       // for asUInt access

    SkBlenderID(uint32_t id) : fID(id) {}

    uint32_t asUInt() const { return fID; }

    uint32_t fID;
};

// When combination options are added to the combination builder an SkCombinationOption
// object is frequently returned. This allows options to be added, recursively, to the
// previously added options.
// Note: SkCombinationOptions are stable memory-wise so, once returned, they are valid
// until SkCombinationBuilder::reset is called.
class SkCombinationOption {
public:
    SkCombinationOption addChildOption(int childIndex, SkShaderType);

    SkCombinationOption addChildOption(int childIndex, SkShaderType,
                                       int minNumStops, int maxNumStops);

    SkCombinationOption addChildOption(int childIndex, SkShaderType,
                                       SkSpan<SkTileModePair> tileModes);

    bool isValid() const { return fDataInArena; }

private:
    friend class SkCombinationBuilder; // for ctor
    friend class CombinationBuilderTestAccess;

    SkCombinationOption(SkCombinationBuilder* builder, SkOption* dataInArena)
            : fBuilder(builder)
            , fDataInArena(dataInArena) {}

    SkShaderType type() const;
    int numChildSlots() const;
    SkDEBUGCODE(int epoch() const;)

    SkCombinationBuilder* fBuilder;
    SkOption* fDataInArena;
};

class SkCombinationBuilder {
public:
    enum class BlendModeGroup {
        kPorterDuff,         // [ kClear .. kScreen ]
        kAdvanced,           // [ kOverlay .. kMultiply ]
        kColorAware,         // [ kHue .. kLuminosity ]
        kAll
    };

    SkCombinationBuilder(SkShaderCodeDictionary*);
    ~SkCombinationBuilder();

    // Blend Modes
    void addOption(SkBlendMode);
    void addOption(SkBlendMode rangeStart, SkBlendMode rangeEnd); // inclusive
    void addOption(BlendModeGroup);

    // TODO: have this variant return an SkCombinationOption object
    void addOption(SkBlenderID);

    // Shaders
    SkCombinationOption addOption(SkShaderType);
    SkCombinationOption addOption(SkShaderType, int minNumStops, int maxNumStops);  // inclusive
    SkCombinationOption addOption(SkShaderType, SkSpan<SkTileModePair> tileModes);

    void reset();

private:
    friend class skgpu::graphite::Context;     // for access to 'buildCombinations'
    friend class SkCombinationOption;          // for 'addOptionInternal' and 'arena'
    friend class CombinationBuilderTestAccess; // for 'num*Combinations' and 'epoch'

    int numShaderCombinations() const;
    int numBlendModeCombinations() const;
    int numCombinations() {
        return this->numShaderCombinations() * this->numBlendModeCombinations();
    }

    // 'desiredCombination' must be less than numCombinations
    void createKey(const SkKeyContext&, int desiredCombination, SkPaintParamsKeyBuilder*);

#ifdef SK_DEBUG
    void dump() const;
    int epoch() const { return fEpoch; }
#endif

    SkArenaAllocWithReset* arena() { return fArena.get(); }

    template<typename T, typename... Args>
    SkOption* allocInArena(Args&&... args);

    SkOption* addOptionInternal(SkShaderType);
    SkOption* addOptionInternal(SkShaderType, int minNumStops, int maxNumStops);
    SkOption* addOptionInternal(SkShaderType, SkSpan<SkTileModePair> tileModes);

    void buildCombinations(SkShaderCodeDictionary*,
                           const std::function<void(SkUniquePaintParamsID)>&);

    SkShaderCodeDictionary* fDictionary;
    std::unique_ptr<SkArenaAllocWithReset> fArena;
    SkTArray<SkOption*> fShaderOptions;

    uint32_t fBlendModes;
    // TODO: store the SkBlender-based blenders in the arena
    SkTHashSet<SkBlenderID> fBlenders;

    SkDEBUGCODE(int fEpoch = 0;)
};

#endif // SK_ENABLE_PRECOMPILE

#endif // SkCombinationBuilder_DEFINED
