// 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/BufferWGPU.h"

#include <algorithm>
#include <string>
#include <utility>

#include "src/dawn/common/StringViewUtils.h"
#include "src/dawn/native/Buffer.h"
#include "src/dawn/native/webgpu/CaptureContext.h"
#include "src/dawn/native/webgpu/DeviceWGPU.h"
#include "src/dawn/native/webgpu/QueueWGPU.h"
#include "src/dawn/native/webgpu/Serialization.h"
#include "src/utils/compiler.h"

namespace dawn::native::webgpu {

// static
ResultOrError<Ref<Buffer>> Buffer::Create(Device* device,
                                          const UnpackedPtr<BufferDescriptor>& descriptor) {
    auto actualUsage = ComputeInternalBufferUsages(device, descriptor->usage, descriptor->size);

    // Make the inner buffer copyable for readback if possible.
    if (!(actualUsage & wgpu::BufferUsage::MapRead)) {
        actualUsage |= wgpu::BufferUsage::CopySrc;
    }

    // Resolve internal usages to regular ones.
    if (actualUsage & kInternalStorageBuffer) {
        actualUsage &= ~kInternalStorageBuffer;
        actualUsage |= wgpu::BufferUsage::Storage;
    }
    if (actualUsage & kReadOnlyStorageBuffer) {
        actualUsage &= ~kReadOnlyStorageBuffer;
        actualUsage |= wgpu::BufferUsage::Storage;
    }
    if (actualUsage & kInternalCopySrcBuffer) {
        actualUsage &= ~kInternalCopySrcBuffer;
        actualUsage |= wgpu::BufferUsage::CopySrc;
    }

    WGPUBufferDescriptor desc = WGPU_BUFFER_DESCRIPTOR_INIT;
    desc.label = ToOutputStringView(descriptor->label);
    desc.usage = ToAPI(actualUsage);
    desc.size = descriptor->size;
    desc.mappedAtCreation = descriptor->mappedAtCreation;

    WGPUBuffer innerBuffer = device->wgpu->deviceCreateBuffer(device->GetInnerHandle(), &desc);
    if (innerBuffer == nullptr) {
        // innerBuffer can be nullptr when mappedAtCreation == true and fails.
        // Return an error buffer.
        const BufferDescriptor* rawDescriptor = *descriptor;
        return ToBackend(BufferBase::MakeError(device, rawDescriptor));
    }

    Ref<Buffer> buffer = AcquireRef(new Buffer(device, descriptor, innerBuffer));
    return std::move(buffer);
}

Buffer::Buffer(Device* device,
               const UnpackedPtr<BufferDescriptor>& descriptor,
               WGPUBuffer innerBuffer)
    : BufferBase(device, descriptor),
      RecordableObject(schema::ObjectType::Buffer),
      ObjectWGPU(device->wgpu->bufferRelease) {
    mInnerHandle = innerBuffer;
    mAllocatedSize = GetSize();
}

bool Buffer::IsCPUWritableAtCreation() const {
    return ToBackend(GetDevice())->wgpu->bufferGetMapState(mInnerHandle) ==
           WGPUBufferMapState_Mapped;
}

MaybeError Buffer::MapAtCreationImpl() {
    // TODO(https://crbug.com/501491697): Spanify along with GetMappedPointerImpl.
    mMappedData = ToBackend(GetDevice())->wgpu->bufferGetMappedRange(mInnerHandle, 0, GetSize());
    return {};
}

MaybeError Buffer::MapAsyncImpl(wgpu::MapMode mode, size_t offset, size_t size) {
    auto deviceGuard = GetDevice()->GetGuard();

    struct MapAsyncResult {
        WGPUMapAsyncStatus status;
        std::string message;
    } mapAsyncResult = {};

    WGPUBufferMapCallbackInfo innerCallbackInfo = {};
    innerCallbackInfo.mode = WGPUCallbackMode_WaitAnyOnly;
    innerCallbackInfo.callback = [](WGPUMapAsyncStatus status, WGPUStringView message,
                                    void* result_param, void* userdata_param) {
        MapAsyncResult* result = reinterpret_cast<MapAsyncResult*>(result_param);
        result->status = status;
        result->message = ToString(message);
    };
    innerCallbackInfo.userdata1 = &mapAsyncResult;
    innerCallbackInfo.userdata2 = this;

    auto& wgpu = ToBackend(GetDevice())->wgpu.get();

    // TODO(crbug.com/413053623): We do not have a way to efficiently process the async event
    // on the inner webgpu layer. For now we simply wait on the future.
    WGPUFutureWaitInfo waitInfo = {};
    waitInfo.future = wgpu.bufferMapAsync(mInnerHandle, static_cast<WGPUMapMode>(mode), offset,
                                          size, innerCallbackInfo);
    wgpu.instanceWaitAny(ToBackend(GetDevice())->GetInnerInstance(), 1, &waitInfo, UINT64_MAX);

    if (mapAsyncResult.status != WGPUMapAsyncStatus_Success) {
        return DAWN_INTERNAL_ERROR(mapAsyncResult.message);
    }

    // The frontend asks that the pointer returned by GetMappedPointer is from the start of
    // the resource but WGPU gives us the pointer at offset. Remove the offset.
    if (bool{mode & wgpu::MapMode::Write}) {
        // TODO(https://crbug.com/501491697): Spanify along with GetMappedPointerImpl.
        mMappedData = DAWN_UNSAFE_TODO(
            static_cast<uint8_t*>(wgpu.bufferGetMappedRange(mInnerHandle, offset, size)) - offset);
    } else if (bool{mode & wgpu::MapMode::Read}) {
        // TODO(https://crbug.com/501491697): Spanify along with GetMappedPointerImpl.
        mMappedData =
            DAWN_UNSAFE_TODO(static_cast<uint8_t*>(const_cast<void*>(
                                 wgpu.bufferGetConstMappedRange(mInnerHandle, offset, size))) -
                             offset);
    } else {
        DAWN_UNREACHABLE();
    }
    return {};
}

MaybeError Buffer::FinalizeMapImpl(BufferState newState) {
    return {};
}

void* Buffer::GetMappedPointerImpl() {
    // The mapping offset has already been removed.
    return mMappedData;
}

void Buffer::UnmapImpl(BufferState oldState, BufferState newState) {
    auto deviceGuard = GetDevice()->GetGuard();

    if (IsMappedState(oldState) && MapMode() == wgpu::MapMode::Write &&
        newState != BufferState::Destroyed) {
        // TODO(477349135): Optimize this by tracking the ranges. As it is we'll
        // capture the entire buffer even if only a few bytes were updated. Instead
        // of mNeedsCapture we could have mDirtySpans. When size is 0 there's nothing to do.
        mNeedsCapture = true;
    }

    if (mInnerHandle) {
        ToBackend(GetDevice())->wgpu->bufferUnmap(mInnerHandle);
    }
    mMappedData = nullptr;
}

void Buffer::DestroyImpl(DestroyReason reason) {
    BufferBase::DestroyImpl(reason);
    auto& wgpu = ToBackend(GetDevice())->wgpu.get();
    wgpu.bufferDestroy(mInnerHandle);
}

void Buffer::SetLabelImpl() {
    ToBackend(GetDevice())->CaptureSetLabel(this, GetLabel());
}

MaybeError Buffer::AddReferenced(CaptureContext& captureContext) {
    // Buffers do not reference other objects.
    return {};
}

MaybeError Buffer::CaptureCreationParameters(CaptureContext& captureContext) {
    schema::Buffer buf{{
        .size = GetSize(),
        .usage = GetUsage(),
    }};
    Serialize(captureContext, buf);
    return {};
}

MaybeError Buffer::CaptureContentIfNeeded(CaptureContext& captureContext,
                                          schema::ObjectId id,
                                          bool newResource) {
    // TODO(451338754): If it's a new resource and we know the buffer is all zero then don't
    // capture.
    wgpu::BufferUsage usage = GetUsage();
    if (!mNeedsCapture && !newResource) {
        return {};
    }

    // A MapRead buffer is never used as input since it's only allowed CopyDst
    // so we don't need its contents.
    if (usage & wgpu::BufferUsage::MapRead) {
        return {};
    }

    mNeedsCapture = false;

    return AddContentToCapture(captureContext);
}

// TODO(451650604): We currently get at most 1mb at a time to keep memory usage down.
// Revisit for speed later.
MaybeError Buffer::AddContentToCapture(CaptureContext& captureContext) {
    // TODO(473593119): Handle the unaligned trailing bytes.
    // TODO(473568230): Support copies with unaligned size.
    // copyBufferToBuffer requires 4 byte alignment for both size and offset which prevents
    // us from copying the trailing bytes. writeBuffer has the same alignment requirements.
    // so the user can't put bytes in via writeBuffer. mapAsync requires offset to be 8 byte
    // aligned and size to be 4 bytes so the user can not set those last bytes with mapAsync.
    // We can still access those bytes with copyBufferToTexture and copyTextureToBuffer though.
    // For now, we just ignore the last 3 bytes.
    uint64_t copyableSize = AlignDown(GetSize(), 4);
    if (copyableSize == 0) {
        return {};
    }

    struct MapAsyncResult {
        WGPUMapAsyncStatus status;
        std::string message;
    } mapAsyncResult = {};

    schema::RootCommandWriteBufferCmd cmd{{
        .data = {{
            .bufferId = captureContext.GetId(this),
            .bufferOffset = 0,
            .size = copyableSize,
        }},
    }};
    Serialize(captureContext, cmd);

    WGPUBuffer srcBuffer = GetInnerHandle();
    WGPUBuffer copyBuffer = captureContext.GetCopyBuffer();
    WGPUQueue queue = ToBackend(GetDevice()->GetQueue())->GetInnerHandle();

    Device* device = ToBackend(GetDevice());
    WGPUDevice innerDevice = device->GetInnerHandle();
    auto& wgpu = device->wgpu.get();

    CaptureContext::ScopedContentWriter writer(captureContext);
    for (uint64_t offset = 0; offset < copyableSize; offset += CaptureContext::kCopyBufferSize) {
        uint64_t copySize = std::min(CaptureContext::kCopyBufferSize, copyableSize - offset);

        WGPUCommandEncoder encoder = wgpu.deviceCreateCommandEncoder(innerDevice, nullptr);
        wgpu.commandEncoderCopyBufferToBuffer(encoder, srcBuffer, offset, copyBuffer, 0, copySize);
        WGPUCommandBuffer commandBuffer = wgpu.commandEncoderFinish(encoder, nullptr);
        wgpu.queueSubmit(queue, 1, &commandBuffer);
        wgpu.commandBufferRelease(commandBuffer);
        wgpu.commandEncoderRelease(encoder);

        // Map the buffer to read back the content.
        WGPUBufferMapCallbackInfo innerCallbackInfo = {};
        innerCallbackInfo.mode = WGPUCallbackMode_WaitAnyOnly;
        innerCallbackInfo.callback = [](WGPUMapAsyncStatus status, WGPUStringView message,
                                        void* result_param, void* userdata_param) {
            MapAsyncResult* result = reinterpret_cast<MapAsyncResult*>(result_param);
            result->status = status;
            result->message = ToString(message);
        };
        innerCallbackInfo.userdata1 = &mapAsyncResult;
        innerCallbackInfo.userdata2 = this;

        // We read this back synchronously. I'm not sure we could do much more.
        WGPUFutureWaitInfo waitInfo = {};
        waitInfo.future =
            wgpu.bufferMapAsync(copyBuffer, WGPUMapMode_Read, 0, copySize, innerCallbackInfo);
        wgpu.instanceWaitAny(device->GetInnerInstance(), 1, &waitInfo, UINT64_MAX);

        DAWN_ASSERT(mapAsyncResult.status == WGPUMapAsyncStatus_Success);

        if (mapAsyncResult.status != WGPUMapAsyncStatus_Success) {
            return DAWN_INTERNAL_ERROR(mapAsyncResult.message);
        }

        const void* data = wgpu.bufferGetConstMappedRange(copyBuffer, 0, copySize);
        writer.WriteContentBytes(data, copySize);
        wgpu.bufferUnmap(copyBuffer);
    }

    return {};
}

}  // namespace dawn::native::webgpu
