// Copyright 2026 The Dawn & Tint Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived from
//    this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "dawn/native/ResourceTableDefaultResources.h"

#include "dawn/common/ityp_array.h"
#include "dawn/native/Device.h"
#include "dawn/native/ResourceTable.h"
#include "dawn/native/Texture.h"
#include "tint/tint.h"

namespace dawn::native {

namespace {
constexpr auto kDefaults = ityp::array<ResourceTableSlot, tint::ResourceType, 35>{
    tint::ResourceType::kTexture1d_f32_filterable,
    tint::ResourceType::kTexture2d_f32_filterable,
    tint::ResourceType::kTexture2dArray_f32_filterable,
    tint::ResourceType::kTextureCube_f32_filterable,
    tint::ResourceType::kTextureCubeArray_f32_filterable,
    tint::ResourceType::kTexture3d_f32_filterable,
    tint::ResourceType::kTexture1d_f32_unfilterable,
    tint::ResourceType::kTexture2d_f32_unfilterable,
    tint::ResourceType::kTexture2dArray_f32_unfilterable,
    tint::ResourceType::kTextureCube_f32_unfilterable,
    tint::ResourceType::kTextureCubeArray_f32_unfilterable,
    tint::ResourceType::kTexture3d_f32_unfilterable,

    tint::ResourceType::kTexture1d_u32,
    tint::ResourceType::kTexture2d_u32,
    tint::ResourceType::kTexture2dArray_u32,
    tint::ResourceType::kTextureCube_u32,
    tint::ResourceType::kTextureCubeArray_u32,
    tint::ResourceType::kTexture3d_u32,

    tint::ResourceType::kTexture1d_i32,
    tint::ResourceType::kTexture2d_i32,
    tint::ResourceType::kTexture2dArray_i32,
    tint::ResourceType::kTextureCube_i32,
    tint::ResourceType::kTextureCubeArray_i32,
    tint::ResourceType::kTexture3d_i32,

    tint::ResourceType::kTextureMultisampled2d_f32,
    tint::ResourceType::kTextureMultisampled2d_u32,
    tint::ResourceType::kTextureMultisampled2d_i32,

    tint::ResourceType::kTextureDepth2d,
    tint::ResourceType::kTextureDepth2dArray,
    tint::ResourceType::kTextureDepthCube,
    tint::ResourceType::kTextureDepthCubeArray,
    tint::ResourceType::kTextureDepthMultisampled2d,

    // If more samplers are added, update kNumDefaultSamplers.
    tint::ResourceType::kSampler_filtering,
    tint::ResourceType::kSampler_non_filtering,
    tint::ResourceType::kSampler_comparison,
};
constexpr auto kNumDefaultSamplers = ResourceTableSlot{3};

// This helper function is used in ASSERTs to check that the default resources are compatible with
// the typeIds that they will be used as defaults for.
[[maybe_unused]] bool AreTypeIDCompatible(tint::ResourceType resourceTypeId,
                                          tint::ResourceType slotTypeId) {
    if (resourceTypeId == slotTypeId) {
        return true;
    }

    // Cases where conversions are allowed:
    switch (slotTypeId) {
        case tint::ResourceType::kTexture1d_f32_unfilterable:
            return resourceTypeId == tint::ResourceType::kTexture1d_f32_filterable;

        case tint::ResourceType::kTexture2d_f32_unfilterable:
            return resourceTypeId == tint::ResourceType::kTexture2d_f32_filterable ||
                   resourceTypeId == tint::ResourceType::kTextureDepth2d;

        case tint::ResourceType::kTexture2dArray_f32_unfilterable:
            return resourceTypeId == tint::ResourceType::kTexture2dArray_f32_filterable ||
                   resourceTypeId == tint::ResourceType::kTextureDepth2dArray;

        case tint::ResourceType::kTextureCube_f32_unfilterable:
            return resourceTypeId == tint::ResourceType::kTextureCube_f32_filterable ||
                   resourceTypeId == tint::ResourceType::kTextureDepthCube;

        case tint::ResourceType::kTextureCubeArray_f32_unfilterable:
            return resourceTypeId == tint::ResourceType::kTextureCubeArray_f32_filterable ||
                   resourceTypeId == tint::ResourceType::kTextureDepthCubeArray;

        case tint::ResourceType::kTexture3d_f32_unfilterable:
            return resourceTypeId == tint::ResourceType::kTexture3d_f32_filterable;

        case tint::ResourceType::kSampler_filtering:
            return resourceTypeId == tint::ResourceType::kSampler_non_filtering;

        default:
            return false;
    }
}
}  // namespace

// static
ResultOrError<std::unique_ptr<ResourceTableDefaultResources>> ResourceTableDefaultResources::Create(
    DeviceBase* device) {
    auto defaults = std::make_unique<ResourceTableDefaultResources>();
    DAWN_TRY(defaults->Initialize(device));
    return defaults;
}

// static
ityp::span<ResourceTableSlot, const tint::ResourceType> ResourceTableDefaultResources::GetOrder() {
    return {kDefaults.data(), ResourceTableSlot(uint32_t(kDefaults.size()))};
}

// static
ResourceTableSlot ResourceTableDefaultResources::GetCount() {
    return GetOrder().size();
}

// static
ResourceTableSlot ResourceTableDefaultResources::GetSamplerCount() {
    return kNumDefaultSamplers;
}

// static
ResourceTableSlot ResourceTableDefaultResources::GetNonSamplerCount() {
    return GetCount() - GetSamplerCount();
}

TextureViewBase* ResourceTableDefaultResources::GetPlaceholderSampleableTexture() const {
    return mPlaceholderSampleableTexture.Get();
}

SamplerBase* ResourceTableDefaultResources::GetPlaceholderSampler() const {
    return mPlaceholderSampler.Get();
}

ityp::span<ResourceTableSlot, const ResourceTableDefaultResources::Resource>
ResourceTableDefaultResources::GetResources() const {
    return {mDefaultResources.data(), mDefaultResources.size()};
}

MaybeError ResourceTableDefaultResources::Initialize(DeviceBase* device) {
    // Each resource is added in the order specified by GetOrder()
    auto AddDefaultTextureView = [&](TextureBase* texture, const TextureViewDescriptor* viewDesc =
                                                               nullptr) -> MaybeError {
        DAWN_TRY(texture->Pin(wgpu::TextureUsage::TextureBinding));

        Ref<TextureViewBase> view;
        DAWN_TRY_ASSIGN(view, device->CreateTextureView(texture, viewDesc));

        // Check that the resource we will have will match the order of default textures that we
        // will give to the shader compilation.
        DAWN_ASSERT(AreTypeIDCompatible(ResourceTableBase::ComputeTypeId(view),
                                        GetOrder()[mDefaultResources.size()]));
        mDefaultResources.push_back(view);

        return {};
    };

    auto AddDefaultSampler = [&](Ref<SamplerBase> sampler) {
        // Check that the resource we will have will match the order of default textures that we
        // will give to the shader compilation.
        DAWN_ASSERT(AreTypeIDCompatible(ResourceTableBase::ComputeTypeId(sampler),
                                        GetOrder()[mDefaultResources.size()]));
        mDefaultResources.push_back(sampler);
    };

    // Create the color format single-sampled views.
    for (auto format :
         {wgpu::TextureFormat::R8Unorm, wgpu::TextureFormat::R8Uint, wgpu::TextureFormat::R8Sint}) {
        // Create the necessary 1/2/3D textures.
        TextureDescriptor tDesc{
            .label = "default SampledTexture resource",
            .usage = wgpu::TextureUsage::TextureBinding,
            .size = {1},
            .format = format,
        };

        tDesc.size = {1};
        tDesc.dimension = wgpu::TextureDimension::e1D;
        Ref<TextureBase> t1D;
        DAWN_TRY_ASSIGN(t1D, device->CreateTexture(&tDesc));

        tDesc.size = {1, 1, 6};
        tDesc.dimension = wgpu::TextureDimension::e2D;
        Ref<TextureBase> t2D;
        DAWN_TRY_ASSIGN(t2D, device->CreateTexture(&tDesc));

        tDesc.size = {1, 1, 1};
        tDesc.dimension = wgpu::TextureDimension::e3D;
        Ref<TextureBase> t3D;
        DAWN_TRY_ASSIGN(t3D, device->CreateTexture(&tDesc));

        // There are two different sets of default resources for R8Unorm because we first add all
        // the filterable f32 sample types, then all the unfilterable f32 sample types.
        uint32_t timesToAdd = format == wgpu::TextureFormat::R8Unorm ? 2 : 1;
        for (uint32_t i = 0; i < timesToAdd; i++) {
            // Create all the default binding view, reusing the 2D texture between
            // 2D/2DArray/Cube/CubeArray.
            DAWN_TRY(AddDefaultTextureView(t1D.Get()));

            TextureViewDescriptor vDesc{
                .label = "default SampledTexture resource",
            };
            vDesc.arrayLayerCount = 1;
            vDesc.dimension = wgpu::TextureViewDimension::e2D;
            DAWN_TRY(AddDefaultTextureView(t2D.Get(), &vDesc));
            vDesc.dimension = wgpu::TextureViewDimension::e2DArray;
            DAWN_TRY(AddDefaultTextureView(t2D.Get(), &vDesc));
            vDesc.arrayLayerCount = 6;
            vDesc.dimension = wgpu::TextureViewDimension::Cube;
            DAWN_TRY(AddDefaultTextureView(t2D.Get(), &vDesc));
            vDesc.dimension = wgpu::TextureViewDimension::CubeArray;
            DAWN_TRY(AddDefaultTextureView(t2D.Get(), &vDesc));

            DAWN_TRY(AddDefaultTextureView(t3D.Get()));
        }

        if (mPlaceholderSampleableTexture == nullptr) {
            DAWN_TRY_ASSIGN(mPlaceholderSampleableTexture,
                            device->CreateTextureView(t2D.Get(), nullptr));
        }
    }

    // Create the color format multi-sampled views.
    for (auto format :
         {wgpu::TextureFormat::R8Unorm, wgpu::TextureFormat::R8Uint, wgpu::TextureFormat::R8Sint}) {
        TextureDescriptor tDesc{
            .label = "default SampledTexture resource",
            .usage = wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::RenderAttachment,
            .dimension = wgpu::TextureDimension::e2D,
            .size = {1, 1},
            .format = format,
            .sampleCount = 4,
        };

        Ref<TextureBase> t;
        DAWN_TRY_ASSIGN(t, device->CreateTexture(&tDesc));
        DAWN_TRY(AddDefaultTextureView(t.Get()));
    }

    // Create the single-sampled depth texture default resource.
    {
        TextureDescriptor tDesc{
            .label = "default SampledTexture resource",
            .usage = wgpu::TextureUsage::TextureBinding,
            .dimension = wgpu::TextureDimension::e2D,
            .size = {1, 1, 6},
            .format = wgpu::TextureFormat::Depth16Unorm,
        };
        Ref<TextureBase> t;
        DAWN_TRY_ASSIGN(t, device->CreateTexture(&tDesc));

        TextureViewDescriptor vDesc{
            .label = "default SampledTexture resource",
        };
        vDesc.arrayLayerCount = 1;
        vDesc.dimension = wgpu::TextureViewDimension::e2D;
        DAWN_TRY(AddDefaultTextureView(t.Get(), &vDesc));
        vDesc.dimension = wgpu::TextureViewDimension::e2DArray;
        DAWN_TRY(AddDefaultTextureView(t.Get(), &vDesc));
        vDesc.arrayLayerCount = 6;
        vDesc.dimension = wgpu::TextureViewDimension::Cube;
        DAWN_TRY(AddDefaultTextureView(t.Get(), &vDesc));
        vDesc.dimension = wgpu::TextureViewDimension::CubeArray;
        DAWN_TRY(AddDefaultTextureView(t.Get(), &vDesc));
    }

    // Create the multi-sampled depth texture default resource.
    {
        TextureDescriptor tDesc{
            .label = "default SampledTexture resource",
            .usage = wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::RenderAttachment,
            .dimension = wgpu::TextureDimension::e2D,
            .size = {1, 1},
            .format = wgpu::TextureFormat::Depth16Unorm,
            .sampleCount = 4,
        };

        Ref<TextureBase> t;
        DAWN_TRY_ASSIGN(t, device->CreateTexture(&tDesc));
        DAWN_TRY(AddDefaultTextureView(t.Get()));
    }

    // Create the samplers.
    {
        // Filtering and non-filtering both use a non-filtering sampler
        {
            SamplerDescriptor sDesc{
                .label = "default Sampler resource",
                .magFilter = wgpu::FilterMode::Nearest,
                .minFilter = wgpu::FilterMode::Nearest,
                .mipmapFilter = wgpu::MipmapFilterMode::Nearest,
            };
            Ref<SamplerBase> s;
            DAWN_TRY_ASSIGN(s, device->CreateSampler(&sDesc));
            AddDefaultSampler(s);  // Filtering
            AddDefaultSampler(s);  // Non-filtering

            mPlaceholderSampler = s;
        }
        // Comparison
        {
            SamplerDescriptor sDesc{
                .label = "default Sampler resource",
                .compare = wgpu::CompareFunction::Always,
            };
            Ref<SamplerBase> s;
            DAWN_TRY_ASSIGN(s, device->CreateSampler(&sDesc));
            AddDefaultSampler(s);
        }
    }

    return {};
}

}  // namespace dawn::native
