// Copyright 2025 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 "src/dawn/native/webgpu/CaptureContext.h"

#include <concepts>
#include <vector>

#include "src/dawn/common/StringViewUtils.h"
#include "src/dawn/native/BlockInfo.h"
#include "src/dawn/native/CommandBuffer.h"
#include "src/dawn/native/Commands.h"
#include "src/dawn/native/Device.h"
#include "src/dawn/native/ObjectBase.h"
#include "src/dawn/native/Surface.h"
#include "src/dawn/native/webgpu/BufferWGPU.h"
#include "src/dawn/native/webgpu/DeviceWGPU.h"
#include "src/dawn/native/webgpu/QuerySetWGPU.h"
#include "src/dawn/native/webgpu/QueueWGPU.h"
#include "src/dawn/native/webgpu/Serialization.h"
#include "src/dawn/native/webgpu/TextureWGPU.h"
#include "src/utils/compiler.h"

namespace dawn::native::webgpu {

CaptureContext::ScopedContentWriter::ScopedContentWriter(CaptureContext& context)
    : mContext(context) {}

CaptureContext::ScopedContentWriter::~ScopedContentWriter() {
    uint64_t offset = mBytesWritten % 4;
    if (offset) {
        static char zero[3] = {0};
        uint64_t paddingNeeded = 4 - offset;
        mContext->WriteContentBytes(zero, paddingNeeded);
    }
}

void CaptureContext::ScopedContentWriter::WriteContentBytes(const void* data, size_t size) {
    mContext->WriteContentBytes(data, size);
    mBytesWritten += size;
}

MaybeError CaptureContext::CaptureCreation(schema::ObjectId id,
                                           const std::string& label,
                                           RecordableObject* object) {
    schema::RootCommandCreateResourceCmd cmd{{
        .data = {{
            .resource = {{
                .type = object->GetObjectType(),
                .id = id,
                .label = label,
            }},
        }},
    }};
    Serialize(*this, cmd);
    return object->CaptureCreationParameters(*this);
}

template <>
void CaptureContext::CaptureSetLabel(Device* object, const std::string& label) {
    schema::RootCommandSetLabelCmd data{{
        .data{{
            .id = schema::kDeviceId,
            .type = schema::ObjectType::Device,
            .label = label,
        }},
    }};
    Serialize(*this, data);
}

template <>
void CaptureContext::CaptureSetLabel(Surface* object, const std::string& label) {
    schema::ObjectId surfaceId = AddResourceAndGetId(object);
    if (surfaceId == 0) {
        return;
    }
    schema::RootCommandSetLabelCmd data{{
        .data{{
            .id = surfaceId,
            .type = schema::ObjectType::Surface,
            .label = label,
        }},
    }};
    Serialize(*this, data);
}

void CaptureContext::CaptureSurfaceConfigure(Surface* surface, const SurfaceConfiguration* config) {
    schema::ObjectId surfaceId = AddResourceAndGetId(surface);
    if (surfaceId == 0) {
        return;
    }

    std::vector<wgpu::TextureFormat> viewFormats;
    for (uint32_t i = 0; i < config->viewFormatCount; ++i) {
        viewFormats.push_back(DAWN_UNSAFE_TODO(config->viewFormats[i]));
    }

    schema::RootCommandSurfaceConfigureCmd cmd{{
        .data = {{
            .surfaceId = surfaceId,
            .config = {{
                .deviceId = schema::kDeviceId,
                .format = config->format,
                .usage = config->usage,
                .viewFormats = viewFormats,
                .alphaMode = config->alphaMode,
                .width = config->width,
                .height = config->height,
                .presentMode = config->presentMode,
            }},
        }},
    }};
    Serialize(*this, cmd);
}

void CaptureContext::CaptureSurfaceUnconfigure(Surface* surface) {
    schema::ObjectId surfaceId = AddResourceAndGetId(surface);
    if (surfaceId == 0) {
        return;
    }
    schema::RootCommandSurfaceUnconfigureCmd cmd{{
        .data = {{
            .surfaceId = surfaceId,
        }},
    }};
    Serialize(*this, cmd);
}

void CaptureContext::CaptureSurfacePresent(Surface* surface) {
    schema::ObjectId surfaceId = AddResourceAndGetId(surface);
    if (surfaceId == 0) {
        return;
    }

    schema::RootCommandSurfacePresentCmd cmd{{
        .data = {{
            .surfaceId = surfaceId,
        }},
    }};
    Serialize(*this, cmd);
}

MaybeError CaptureContext::CaptureSurfaceGetCurrentTexture(Surface* surface, Texture* texture) {
    schema::ObjectId surfaceId = AddResourceAndGetId(surface);
    if (surfaceId == 0) {
        return {};
    }
    schema::ObjectId textureId;
    DAWN_TRY_ASSIGN(textureId, AddResourceAndGetId(texture));
    if (textureId == 0) {
        return {};
    }

    schema::RootCommandSurfaceGetCurrentTextureCmd cmd{{
        .data = {{
            .surfaceId = surfaceId,
            .textureId = textureId,
        }},
    }};
    Serialize(*this, cmd);
    return {};
}

schema::ObjectId CaptureContext::AddResourceAndGetId(Surface* surface) {
    DAWN_ASSERT(surface != nullptr);
    Ref<Surface> ref(surface);
    auto it = mSurfaceIds.find(ref);
    if (it == mSurfaceIds.end()) {
        schema::ObjectId id = mNextObjectId++;
        mSurfaceIds[std::move(ref)] = id;
        return id;
    }
    return it->second;
}

schema::ObjectId CaptureContext::GetId(Surface* surface) {
    if (surface == nullptr) {
        return 0;
    }

    auto it = mSurfaceIds.find(Ref<Surface>(surface));
    DAWN_ASSERT(it != mSurfaceIds.end());
    return it->second;
}

CaptureContext::CaptureContext(Device* device,
                               std::ostream& commandStream,
                               std::ostream& contentStream)
    : mDevice(device), mCommandStream(commandStream), mContentStream(contentStream) {}

void CaptureContext::ReleaseReferences() {
    mObjectIds.clear();
    mSurfaceIds.clear();

    if (mDevice) {
        auto& wgpu = mDevice->wgpu;
        if (mCopyBuffer) {
            wgpu->bufferDestroy(mCopyBuffer);
            wgpu->bufferRelease(mCopyBuffer);
        }

        mDevice = nullptr;
    }
}

CaptureContext::~CaptureContext() {
    ReleaseReferences();
}

WGPUBuffer CaptureContext::GetCopyBuffer() {
    if (!mCopyBuffer) {
        WGPUBufferDescriptor desc = {};
        // Add a label to the copy buffer for better debugging experience.
        desc.label = ToOutputStringView("Capture Copy Buffer");
        desc.size = kCopyBufferSize;
        desc.usage = WGPUBufferUsage_CopyDst | WGPUBufferUsage_MapRead;
        mCopyBuffer = mDevice->wgpu->deviceCreateBuffer(mDevice->GetInnerHandle(), &desc);
    }
    return mCopyBuffer;
}

void CaptureContext::WriteContentBytes(const void* data, size_t size) {
    mContentStream->write(reinterpret_cast<const char*>(data), size);
}

void CaptureContext::WriteCommandBytes(const void* data, size_t size) {
    mCommandStream->write(reinterpret_cast<const char*>(data), size);
    mCommandBytesWritten += size;
}

MaybeError CaptureContext::CaptureQueueWriteBuffer(Buffer* buffer,
                                                   uint64_t bufferOffset,
                                                   const void* data,
                                                   size_t size) {
    schema::ObjectId id;
    DAWN_TRY_ASSIGN(id, AddResourceAndGetId(buffer));
    schema::RootCommandWriteBufferCmd cmd{{
        .data = {{
            .bufferId = id,
            .bufferOffset = bufferOffset,
            .size = size,
        }},
    }};

    Serialize(*this, cmd);
    WriteContentBytes(data, size);
    return {};
}

MaybeError CaptureContext::CaptureQueueWriteTexture(const TexelCopyTextureInfo& destination,
                                                    const void* data,
                                                    size_t dataSize,
                                                    const TexelCopyBufferLayout& dataLayout,
                                                    const TexelExtent3D& writeSizePixel) {
    DAWN_TRY(AddResource(ToBackend(destination.texture)));
    schema::RootCommandWriteTextureCmd cmd{{
        .data = {{
            .destination = ToSchema(*this, destination),
            .layout = ToSchema(dataLayout),
            .size = ToSchema(writeSizePixel),
            .dataSize = dataSize,
        }},
    }};
    Serialize(*this, cmd);

    CaptureContext::ScopedContentWriter writer(*this);
    writer.WriteContentBytes(data, dataSize);
    return {};
}

wgpu::TextureAspect ToDawn(const Aspect aspect) {
    switch (aspect) {
        case Aspect::Depth:
            return wgpu::TextureAspect::DepthOnly;
        case Aspect::Stencil:
            return wgpu::TextureAspect::StencilOnly;
        case Aspect::Plane0:
            return wgpu::TextureAspect::Plane0Only;
        case Aspect::Plane1:
            return wgpu::TextureAspect::Plane1Only;
        case Aspect::Plane2:
            return wgpu::TextureAspect::Plane2Only;
        default:
            return wgpu::TextureAspect::All;
    }
}

schema::Origin3D ToSchema(const TexelOrigin3D& origin) {
    return {{
        .x = dchecked_cast<uint32_t>(origin.x),
        .y = dchecked_cast<uint32_t>(origin.y),
        .z = dchecked_cast<uint32_t>(origin.z),
    }};
}

schema::Origin2D ToSchema(const Origin2D& origin) {
    return {{
        .x = origin.x,
        .y = origin.y,
    }};
}

schema::Extent3D ToSchema(const TexelExtent3D& extent) {
    return {{
        .width = dchecked_cast<uint32_t>(extent.width),
        .height = dchecked_cast<uint32_t>(extent.height),
        .depthOrArrayLayers = dchecked_cast<uint32_t>(extent.depthOrArrayLayers),
    }};
}

schema::Extent2D ToSchema(const Extent2D& extent) {
    return {{
        .width = extent.width,
        .height = extent.height,
    }};
}

schema::Color ToSchema(const Color& color) {
    return {{
        .r = color.r,
        .g = color.g,
        .b = color.b,
        .a = color.a,
    }};
}

schema::TexelCopyBufferLayout ToSchema(const BufferCopy& bufferCopy,
                                       const TypedTexelBlockInfo& blockInfo) {
    return {{
        .offset = bufferCopy.offset,
        .bytesPerRow = static_cast<uint32_t>(blockInfo.ToBytes(bufferCopy.blocksPerRow)),
        .rowsPerImage = dchecked_cast<uint32_t>(bufferCopy.rowsPerImage),
    }};
}

schema::TexelCopyBufferInfo ToSchema(CaptureContext& captureContext,
                                     const BufferCopy& bufferCopy,
                                     const TypedTexelBlockInfo& blockInfo) {
    return {{
        .bufferId = captureContext.GetId(bufferCopy.buffer),
        .layout = ToSchema(bufferCopy, blockInfo),
    }};
}

schema::TexelCopyTextureInfo ToSchema(CaptureContext& captureContext,
                                      const TextureCopy& textureCopy) {
    return {{
        .textureId = captureContext.GetId(textureCopy.texture),
        .mipLevel = textureCopy.mipLevel,
        .origin = ToSchema(textureCopy.origin),
        .aspect = ToDawn(textureCopy.aspect),
    }};
}

schema::TexelCopyBufferLayout ToSchema(const TexelCopyBufferLayout& layout) {
    return {{
        .offset = layout.offset,
        .bytesPerRow = layout.bytesPerRow,
        .rowsPerImage = layout.rowsPerImage,
    }};
}

schema::TexelCopyTextureInfo ToSchema(CaptureContext& captureContext,
                                      const TexelCopyTextureInfo& info) {
    return {{
        .textureId = captureContext.GetId(info.texture),
        .mipLevel = info.mipLevel,
        .origin = ToSchema(info.origin),
        .aspect = info.aspect,
    }};
}

schema::TimestampWrites ToSchema(CaptureContext& captureContext,
                                 const TimestampWrites& timestampWrites) {
    return {{
        .querySetId = captureContext.GetId(timestampWrites.querySet),
        .beginningOfPassWriteIndex = uint32_t{timestampWrites.beginningOfPassWriteIndex},
        .endOfPassWriteIndex = uint32_t{timestampWrites.endOfPassWriteIndex},
    }};
}

schema::ProgrammableStage ToSchema(CaptureContext& captureContext, const ProgrammableStage& stage) {
    std::vector<schema::PipelineConstant> constants;
    for (const auto& [name, value] : stage.constants) {
        constants.push_back({{
            .name = name,
            .value = value,
        }});
    }
    return {{
        .moduleId = captureContext.GetId(stage.module.Get()),
        .entryPoint = stage.entryPoint,
        .constants = constants,
    }};
}

}  // namespace dawn::native::webgpu
