// Copyright 2019 The Dawn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "dawn_wire/client/Buffer.h"

#include "dawn_wire/BufferConsumer_impl.h"
#include "dawn_wire/WireCmd_autogen.h"
#include "dawn_wire/client/Client.h"
#include "dawn_wire/client/Device.h"

namespace dawn_wire::client {

    // static
    WGPUBuffer Buffer::Create(Device* device, const WGPUBufferDescriptor* descriptor) {
        Client* wireClient = device->client;

        bool mappable =
            (descriptor->usage & (WGPUBufferUsage_MapRead | WGPUBufferUsage_MapWrite)) != 0 ||
            descriptor->mappedAtCreation;
        if (mappable && descriptor->size >= std::numeric_limits<size_t>::max()) {
            device->InjectError(WGPUErrorType_OutOfMemory, "Buffer is too large for map usage");
            return device->CreateErrorBuffer();
        }

        std::unique_ptr<MemoryTransferService::ReadHandle> readHandle = nullptr;
        std::unique_ptr<MemoryTransferService::WriteHandle> writeHandle = nullptr;

        DeviceCreateBufferCmd cmd;
        cmd.deviceId = device->id;
        cmd.descriptor = descriptor;
        cmd.readHandleCreateInfoLength = 0;
        cmd.readHandleCreateInfo = nullptr;
        cmd.writeHandleCreateInfoLength = 0;
        cmd.writeHandleCreateInfo = nullptr;

        if (mappable) {
            if ((descriptor->usage & WGPUBufferUsage_MapRead) != 0) {
                // Create the read handle on buffer creation.
                readHandle.reset(
                    wireClient->GetMemoryTransferService()->CreateReadHandle(descriptor->size));
                if (readHandle == nullptr) {
                    device->InjectError(WGPUErrorType_OutOfMemory,
                                        "Failed to create buffer mapping");
                    return device->CreateErrorBuffer();
                }
                cmd.readHandleCreateInfoLength = readHandle->SerializeCreateSize();
            }

            if ((descriptor->usage & WGPUBufferUsage_MapWrite) != 0 ||
                descriptor->mappedAtCreation) {
                // Create the write handle on buffer creation.
                writeHandle.reset(
                    wireClient->GetMemoryTransferService()->CreateWriteHandle(descriptor->size));
                if (writeHandle == nullptr) {
                    device->InjectError(WGPUErrorType_OutOfMemory,
                                        "Failed to create buffer mapping");
                    return device->CreateErrorBuffer();
                }
                cmd.writeHandleCreateInfoLength = writeHandle->SerializeCreateSize();
            }
        }

        // Create the buffer and send the creation command.
        // This must happen after any potential device->CreateErrorBuffer()
        // as server expects allocating ids to be monotonically increasing
        auto* bufferObjectAndSerial = wireClient->BufferAllocator().New(wireClient);
        Buffer* buffer = bufferObjectAndSerial->object.get();
        buffer->mDevice = device;
        buffer->mDeviceIsAlive = device->GetAliveWeakPtr();
        buffer->mSize = descriptor->size;
        buffer->mDestructWriteHandleOnUnmap = false;

        if (descriptor->mappedAtCreation) {
            // If the buffer is mapped at creation, a write handle is created and will be
            // destructed on unmap if the buffer doesn't have MapWrite usage
            // The buffer is mapped right now.
            buffer->mMapState = MapState::MappedAtCreation;

            // This flag is for write handle created by mappedAtCreation
            // instead of MapWrite usage. We don't have such a case for read handle
            buffer->mDestructWriteHandleOnUnmap =
                (descriptor->usage & WGPUBufferUsage_MapWrite) == 0;

            buffer->mMapOffset = 0;
            buffer->mMapSize = buffer->mSize;
            ASSERT(writeHandle != nullptr);
            buffer->mMappedData = writeHandle->GetData();
        }

        cmd.result = ObjectHandle{buffer->id, bufferObjectAndSerial->generation};

        wireClient->SerializeCommand(
            cmd, cmd.readHandleCreateInfoLength + cmd.writeHandleCreateInfoLength,
            [&](SerializeBuffer* serializeBuffer) {
                if (readHandle != nullptr) {
                    char* readHandleBuffer;
                    WIRE_TRY(
                        serializeBuffer->NextN(cmd.readHandleCreateInfoLength, &readHandleBuffer));
                    // Serialize the ReadHandle into the space after the command.
                    readHandle->SerializeCreate(readHandleBuffer);
                    buffer->mReadHandle = std::move(readHandle);
                }
                if (writeHandle != nullptr) {
                    char* writeHandleBuffer;
                    WIRE_TRY(serializeBuffer->NextN(cmd.writeHandleCreateInfoLength,
                                                    &writeHandleBuffer));
                    // Serialize the WriteHandle into the space after the command.
                    writeHandle->SerializeCreate(writeHandleBuffer);
                    buffer->mWriteHandle = std::move(writeHandle);
                }

                return WireResult::Success;
            });
        return ToAPI(buffer);
    }

    // static
    WGPUBuffer Buffer::CreateError(Device* device) {
        auto* allocation = device->client->BufferAllocator().New(device->client);
        allocation->object->mDevice = device;
        allocation->object->mDeviceIsAlive = device->GetAliveWeakPtr();

        DeviceCreateErrorBufferCmd cmd;
        cmd.self = ToAPI(device);
        cmd.result = ObjectHandle{allocation->object->id, allocation->generation};
        device->client->SerializeCommand(cmd);

        return ToAPI(allocation->object.get());
    }

    Buffer::~Buffer() {
        ClearAllCallbacks(WGPUBufferMapAsyncStatus_DestroyedBeforeCallback);
        FreeMappedData();
    }

    void Buffer::CancelCallbacksForDisconnect() {
        ClearAllCallbacks(WGPUBufferMapAsyncStatus_DeviceLost);
    }

    void Buffer::ClearAllCallbacks(WGPUBufferMapAsyncStatus status) {
        mRequests.CloseAll([status](MapRequestData* request) {
            if (request->callback != nullptr) {
                request->callback(status, request->userdata);
            }
        });
    }

    void Buffer::MapAsync(WGPUMapModeFlags mode,
                          size_t offset,
                          size_t size,
                          WGPUBufferMapCallback callback,
                          void* userdata) {
        if (client->IsDisconnected()) {
            return callback(WGPUBufferMapAsyncStatus_DeviceLost, userdata);
        }

        // Handle the defaulting of size required by WebGPU.
        if ((size == WGPU_WHOLE_MAP_SIZE) && (offset <= mSize)) {
            size = mSize - offset;
        }

        // Create the request structure that will hold information while this mapping is
        // in flight.
        MapRequestData request = {};
        request.callback = callback;
        request.userdata = userdata;
        request.offset = offset;
        request.size = size;
        if (mode & WGPUMapMode_Read) {
            request.type = MapRequestType::Read;
        } else if (mode & WGPUMapMode_Write) {
            request.type = MapRequestType::Write;
        }

        uint64_t serial = mRequests.Add(std::move(request));

        // Serialize the command to send to the server.
        BufferMapAsyncCmd cmd;
        cmd.bufferId = this->id;
        cmd.requestSerial = serial;
        cmd.mode = mode;
        cmd.offset = offset;
        cmd.size = size;

        client->SerializeCommand(cmd);
    }

    bool Buffer::OnMapAsyncCallback(uint64_t requestSerial,
                                    uint32_t status,
                                    uint64_t readDataUpdateInfoLength,
                                    const uint8_t* readDataUpdateInfo) {
        MapRequestData request;
        if (!mRequests.Acquire(requestSerial, &request)) {
            return false;
        }

        auto FailRequest = [&request]() -> bool {
            if (request.callback != nullptr) {
                request.callback(WGPUBufferMapAsyncStatus_DeviceLost, request.userdata);
            }
            return false;
        };

        // Take into account the client-side status of the request if the server says it is a success.
        if (status == WGPUBufferMapAsyncStatus_Success) {
            status = request.clientStatus;
        }

        if (status == WGPUBufferMapAsyncStatus_Success) {
            switch (request.type) {
                case MapRequestType::Read: {
                    if (readDataUpdateInfoLength > std::numeric_limits<size_t>::max()) {
                        // This is the size of data deserialized from the command stream, which must
                        // be CPU-addressable.
                        return FailRequest();
                    }

                    // Validate to prevent bad map request; buffer destroyed during map request
                    if (mReadHandle == nullptr) {
                        return FailRequest();
                    }
                    // Update user map data with server returned data
                    if (!mReadHandle->DeserializeDataUpdate(
                            readDataUpdateInfo, static_cast<size_t>(readDataUpdateInfoLength),
                            request.offset, request.size)) {
                        return FailRequest();
                    }
                    mMapState = MapState::MappedForRead;
                    mMappedData = const_cast<void*>(mReadHandle->GetData());
                    break;
                }
                case MapRequestType::Write: {
                    if (mWriteHandle == nullptr) {
                        return FailRequest();
                    }
                    mMapState = MapState::MappedForWrite;
                    mMappedData = mWriteHandle->GetData();
                    break;
                }
                default:
                    UNREACHABLE();
            }

            mMapOffset = request.offset;
            mMapSize = request.size;
        }

        if (request.callback) {
            request.callback(static_cast<WGPUBufferMapAsyncStatus>(status), request.userdata);
        }

        return true;
    }

    void* Buffer::GetMappedRange(size_t offset, size_t size) {
        if (!IsMappedForWriting() || !CheckGetMappedRangeOffsetSize(offset, size)) {
            return nullptr;
        }
        return static_cast<uint8_t*>(mMappedData) + offset;
    }

    const void* Buffer::GetConstMappedRange(size_t offset, size_t size) {
        if (!(IsMappedForWriting() || IsMappedForReading()) ||
            !CheckGetMappedRangeOffsetSize(offset, size)) {
            return nullptr;
        }
        return static_cast<uint8_t*>(mMappedData) + offset;
    }

    void Buffer::Unmap() {
        // Invalidate the local pointer, and cancel all other in-flight requests that would
        // turn into errors anyway (you can't double map). This prevents race when the following
        // happens, where the application code would have unmapped a buffer but still receive a
        // callback:
        //   - Client -> Server: MapRequest1, Unmap, MapRequest2
        //   - Server -> Client: Result of MapRequest1
        //   - Unmap locally on the client
        //   - Server -> Client: Result of MapRequest2

        // mWriteHandle can still be nullptr if buffer has been destroyed before unmap
        if ((mMapState == MapState::MappedForWrite || mMapState == MapState::MappedAtCreation) &&
            mWriteHandle != nullptr) {
            // Writes need to be flushed before Unmap is sent. Unmap calls all associated
            // in-flight callbacks which may read the updated data.

            // Get the serialization size of data update writes.
            size_t writeDataUpdateInfoLength =
                mWriteHandle->SizeOfSerializeDataUpdate(mMapOffset, mMapSize);

            BufferUpdateMappedDataCmd cmd;
            cmd.bufferId = id;
            cmd.writeDataUpdateInfoLength = writeDataUpdateInfoLength;
            cmd.writeDataUpdateInfo = nullptr;
            cmd.offset = mMapOffset;
            cmd.size = mMapSize;

            client->SerializeCommand(
                cmd, writeDataUpdateInfoLength, [&](SerializeBuffer* serializeBuffer) {
                    char* writeHandleBuffer;
                    WIRE_TRY(serializeBuffer->NextN(writeDataUpdateInfoLength, &writeHandleBuffer));

                    // Serialize flush metadata into the space after the command.
                    // This closes the handle for writing.
                    mWriteHandle->SerializeDataUpdate(writeHandleBuffer, cmd.offset, cmd.size);

                    return WireResult::Success;
                });

            // If mDestructWriteHandleOnUnmap is true, that means the write handle is merely
            // for mappedAtCreation usage. It is destroyed on unmap after flush to server
            // instead of at buffer destruction.
            if (mMapState == MapState::MappedAtCreation && mDestructWriteHandleOnUnmap) {
                mWriteHandle = nullptr;
                if (mReadHandle) {
                    // If it's both mappedAtCreation and MapRead we need to reset
                    // mMappedData to readHandle's GetData(). This could be changed to
                    // merging read/write handle in future
                    mMappedData = const_cast<void*>(mReadHandle->GetData());
                }
            }
        }

        // Free map access tokens
        mMapState = MapState::Unmapped;
        mMapOffset = 0;
        mMapSize = 0;

        // Tag all mapping requests still in flight as unmapped before callback.
        mRequests.ForAll([](MapRequestData* request) {
            if (request->clientStatus == WGPUBufferMapAsyncStatus_Success) {
                request->clientStatus = WGPUBufferMapAsyncStatus_UnmappedBeforeCallback;
            }
        });

        BufferUnmapCmd cmd;
        cmd.self = ToAPI(this);
        client->SerializeCommand(cmd);
    }

    void Buffer::Destroy() {
        // Remove the current mapping and destroy Read/WriteHandles.
        FreeMappedData();

        // Tag all mapping requests still in flight as destroyed before callback.
        mRequests.ForAll([](MapRequestData* request) {
            if (request->clientStatus == WGPUBufferMapAsyncStatus_Success) {
                request->clientStatus = WGPUBufferMapAsyncStatus_DestroyedBeforeCallback;
            }
        });

        BufferDestroyCmd cmd;
        cmd.self = ToAPI(this);
        client->SerializeCommand(cmd);
    }

    bool Buffer::IsMappedForReading() const {
        return mMapState == MapState::MappedForRead;
    }

    bool Buffer::IsMappedForWriting() const {
        return mMapState == MapState::MappedForWrite || mMapState == MapState::MappedAtCreation;
    }

    bool Buffer::CheckGetMappedRangeOffsetSize(size_t offset, size_t size) const {
        if (offset % 8 != 0 || size % 4 != 0) {
            return false;
        }

        if (size > mMapSize || offset < mMapOffset) {
            return false;
        }

        size_t offsetInMappedRange = offset - mMapOffset;
        return offsetInMappedRange <= mMapSize - size;
    }

    void Buffer::FreeMappedData() {
#if defined(DAWN_ENABLE_ASSERTS)
        // When in "debug" mode, 0xCA-out the mapped data when we free it so that in we can detect
        // use-after-free of the mapped data. This is particularly useful for WebGPU test about the
        // interaction of mapping and GC.
        if (mMappedData) {
            memset(static_cast<uint8_t*>(mMappedData) + mMapOffset, 0xCA, mMapSize);
        }
#endif  // defined(DAWN_ENABLE_ASSERTS)

        mMapOffset = 0;
        mMapSize = 0;
        mReadHandle = nullptr;
        mWriteHandle = nullptr;
        mMappedData = nullptr;
    }

}  // namespace dawn_wire::client
