#pragma once

#include <Graphics/Colors.h>
#include <Graphics/Texture.h>

namespace Juliet
{
    enum struct LoadOperation : uint8
    {
        Load,  // Load the texture from memory (preserve)
        Clear, // Clear the texture
        Ignore // Ignore the content of the texture (undefined)
    };

    enum struct StoreOperation : uint8
    {
        Store,          // Store the result of the render pass into memory
        Ignore,         // Whatever is generated is ignored (undefined)
        Resolve,        // Resolve MipMaps into non mip map texture. Discard MipMap content
        ResolveAndStore // Same but store the MipMap content to memory
    };

    struct ColorTargetInfo
    {
        Texture* TargetTexture;
        uint32   MipLevel;
        union
        {
            uint32 DepthPlane;
            uint32 LayerIndex;
        };
        bool CycleTexture; // Whether the texture should be cycled if already bound (and load operation != LOAD)

        Texture* ResolveTexture;
        uint32   ResolveMipLevel;
        uint32   ResolveLayerIndex;
        bool     CycleResolveTexture;

        FColor         ClearColor;
        LoadOperation  LoadOperation;
        StoreOperation StoreOperation;
    };

    struct DepthStencilTargetInfo
    {
        Texture* TargetTexture;
        uint32   MipLevel;
        uint32   LayerIndex;

        float         ClearDepth;
        uint8         ClearStencil;
        LoadOperation LoadOperation;
        StoreOperation StoreOperation;
    };
 
     enum class BlendFactor : uint8
    {
        Invalid,
        Zero,
        One,
        Src_Color,
        One_Minus_Src_Color,
        Dst_Color,
        One_Minus_Dst_Color,
        Src_Alpha,
        One_Minus_Src_Alpha,
        Dst_Alpha,
        One_Minus_Dst_Alpha,
        Constant_Color,
        One_MINUS_Constant_Color,
        Src_Alpha_Saturate, // min(source alpha, 1 - destination alpha)
        Count
    };

    enum class BlendOperation : uint8
    {
        Invalid,
        Add,             // (source * source_factor) + (destination * destination_factor)
        Subtract,        // (source * source_factor) - (destination * destination_factor)
        ReverseSubtract, // (destination * destination_factor) - (source * source_factor)
        Min,             // min(source, destination)
        Max,             // max(source, destination)
        Count
    };

    enum class ColorComponentFlags : uint8
    {
        R = 1u << 0,
        G = 1u << 1,
        B = 1u << 2,
        A = 1u << 3
    };

    struct ColorTargetBlendState
    {
        BlendFactor    SourceColorBlendFactor;      // The value to be multiplied by the source RGB value.
        BlendFactor    DestinationColorBlendFactor; // The value to be multiplied by the destination RGB value.
        BlendOperation ColorBlendOperation;         // The blend operation for the RGB components.
        BlendFactor    SourceAlphaBlendFactor;      // The value to be multiplied by the source alpha.
        BlendFactor    DestinationAlphaBlendFactor; // The value to be multiplied by the destination alpha.
        BlendOperation AlphaBlendOperation;         // The blend operation for the alpha component.
        ColorComponentFlags ColorWriteMask; // A bitmask specifying which of the RGBA components are enabled for writing. Writes to all channels if enable_color_write_mask is false.
        bool EnableBlend : 1;               // Whether blending is enabled for the color target.
        bool EnableColorWriteMask : 1;      // Whether the color write mask is enabled.
    };

    struct ColorTargetDescription
    {
        TextureFormat         Format;
        ColorTargetBlendState BlendState;
    };

    // Opaque Type
    struct RenderPass;
} // namespace Juliet
