// 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 <limits>
#include <memory>

#include "dawn/common/Assert.h"
#include "dawn/wire/BufferConsumer_impl.h"
#include "dawn/wire/WireCmd_autogen.h"
#include "dawn/wire/server/Server.h"

namespace dawn::wire::server {

bool Server::PreHandleBufferUnmap(const BufferUnmapCmd& cmd) {
    auto* buffer = BufferObjects().Get(cmd.selfId);
    DAWN_ASSERT(buffer != nullptr);

    if (buffer->mappedAtCreation && !(buffer->usage & WGPUMapMode_Write)) {
        // This indicates the writeHandle is for mappedAtCreation only. Destroy on unmap
        // writeHandle could have possibly been deleted if buffer is already destroyed so we
        // don't assert it's non-null
        buffer->writeHandle = nullptr;
    }

    buffer->mapWriteState = BufferMapWriteState::Unmapped;

    return true;
}

bool Server::PreHandleBufferDestroy(const BufferDestroyCmd& cmd) {
    // Destroying a buffer does an implicit unmapping.
    auto* buffer = BufferObjects().Get(cmd.selfId);
    DAWN_ASSERT(buffer != nullptr);

    // The buffer was destroyed. Clear the Read/WriteHandle.
    buffer->readHandle = nullptr;
    buffer->writeHandle = nullptr;
    buffer->mapWriteState = BufferMapWriteState::Unmapped;

    return true;
}

bool Server::DoBufferMapAsync(ObjectId bufferId,
                              uint64_t requestSerial,
                              WGPUMapModeFlags mode,
                              uint64_t offset64,
                              uint64_t size64) {
    // These requests are just forwarded to the buffer, with userdata containing what the
    // client will require in the return command.

    // The null object isn't valid as `self`
    if (bufferId == 0) {
        return false;
    }

    auto* buffer = BufferObjects().Get(bufferId);
    if (buffer == nullptr) {
        return false;
    }

    std::unique_ptr<MapUserdata> userdata = MakeUserdata<MapUserdata>();
    userdata->buffer = ObjectHandle{bufferId, buffer->generation};
    userdata->bufferObj = buffer->handle;
    userdata->requestSerial = requestSerial;
    userdata->mode = mode;

    // Make sure that the deserialized offset and size are no larger than
    // std::numeric_limits<size_t>::max() so that they are CPU-addressable, and size is not
    // WGPU_WHOLE_MAP_SIZE, which is by definition std::numeric_limits<size_t>::max(). Since
    // client does the default size computation, we should always have a valid actual size here
    // in server. All other invalid actual size can be caught by dawn native side validation.
    if (offset64 > std::numeric_limits<size_t>::max() || size64 >= WGPU_WHOLE_MAP_SIZE) {
        OnBufferMapAsyncCallback(userdata.get(), WGPUBufferMapAsyncStatus_Error);
        return true;
    }

    size_t offset = static_cast<size_t>(offset64);
    size_t size = static_cast<size_t>(size64);

    userdata->offset = offset;
    userdata->size = size;

    mProcs.bufferMapAsync(buffer->handle, mode, offset, size,
                          ForwardToServer<&Server::OnBufferMapAsyncCallback>, userdata.release());

    return true;
}

bool Server::DoDeviceCreateBuffer(ObjectId deviceId,
                                  const WGPUBufferDescriptor* descriptor,
                                  ObjectHandle bufferResult,
                                  uint64_t readHandleCreateInfoLength,
                                  const uint8_t* readHandleCreateInfo,
                                  uint64_t writeHandleCreateInfoLength,
                                  const uint8_t* writeHandleCreateInfo) {
    auto* device = DeviceObjects().Get(deviceId);
    if (device == nullptr) {
        return false;
    }

    // Create and register the buffer object.
    auto* resultData = BufferObjects().Allocate(bufferResult.id);
    if (resultData == nullptr) {
        return false;
    }
    resultData->generation = bufferResult.generation;
    resultData->handle = mProcs.deviceCreateBuffer(device->handle, descriptor);
    resultData->deviceInfo = device->info.get();
    resultData->usage = descriptor->usage;
    resultData->mappedAtCreation = descriptor->mappedAtCreation;
    if (!TrackDeviceChild(resultData->deviceInfo, ObjectType::Buffer, bufferResult.id)) {
        return false;
    }

    // isReadMode and isWriteMode could be true at the same time if usage contains
    // WGPUMapMode_Read and buffer is mappedAtCreation
    bool isReadMode = descriptor->usage & WGPUMapMode_Read;
    bool isWriteMode = descriptor->usage & WGPUMapMode_Write || descriptor->mappedAtCreation;

    // This is the size of data deserialized from the command stream to create the read/write
    // handle, which must be CPU-addressable.
    if (readHandleCreateInfoLength > std::numeric_limits<size_t>::max() ||
        writeHandleCreateInfoLength > std::numeric_limits<size_t>::max() ||
        readHandleCreateInfoLength >
            std::numeric_limits<size_t>::max() - writeHandleCreateInfoLength) {
        return false;
    }

    if (isWriteMode) {
        MemoryTransferService::WriteHandle* writeHandle = nullptr;
        // Deserialize metadata produced from the client to create a companion server handle.
        if (!mMemoryTransferService->DeserializeWriteHandle(
                writeHandleCreateInfo, static_cast<size_t>(writeHandleCreateInfoLength),
                &writeHandle)) {
            return false;
        }
        ASSERT(writeHandle != nullptr);
        resultData->writeHandle.reset(writeHandle);
        writeHandle->SetDataLength(descriptor->size);

        if (descriptor->mappedAtCreation) {
            void* mapping = mProcs.bufferGetMappedRange(resultData->handle, 0, descriptor->size);
            if (mapping == nullptr) {
                // A zero mapping is used to indicate an allocation error of an error buffer.
                // This is a valid case and isn't fatal. Remember the buffer is an error so as
                // to skip subsequent mapping operations.
                resultData->mapWriteState = BufferMapWriteState::MapError;
                return true;
            }
            ASSERT(mapping != nullptr);
            writeHandle->SetTarget(mapping);

            resultData->mapWriteState = BufferMapWriteState::Mapped;
        }
    }

    if (isReadMode) {
        MemoryTransferService::ReadHandle* readHandle = nullptr;
        // Deserialize metadata produced from the client to create a companion server handle.
        if (!mMemoryTransferService->DeserializeReadHandle(
                readHandleCreateInfo, static_cast<size_t>(readHandleCreateInfoLength),
                &readHandle)) {
            return false;
        }
        ASSERT(readHandle != nullptr);

        resultData->readHandle.reset(readHandle);
    }

    return true;
}

bool Server::DoBufferUpdateMappedData(ObjectId bufferId,
                                      uint64_t writeDataUpdateInfoLength,
                                      const uint8_t* writeDataUpdateInfo,
                                      uint64_t offset,
                                      uint64_t size) {
    // The null object isn't valid as `self`
    if (bufferId == 0) {
        return false;
    }

    if (writeDataUpdateInfoLength > std::numeric_limits<size_t>::max() ||
        offset > std::numeric_limits<size_t>::max() || size > std::numeric_limits<size_t>::max()) {
        return false;
    }

    auto* buffer = BufferObjects().Get(bufferId);
    if (buffer == nullptr) {
        return false;
    }
    switch (buffer->mapWriteState) {
        case BufferMapWriteState::Unmapped:
            return false;
        case BufferMapWriteState::MapError:
            // The buffer is mapped but there was an error allocating mapped data.
            // Do not perform the memcpy.
            return true;
        case BufferMapWriteState::Mapped:
            break;
    }
    if (!buffer->writeHandle) {
        // This check is performed after the check for the MapError state. It is permissible
        // to Unmap and attempt to update mapped data of an error buffer.
        return false;
    }

    // Deserialize the flush info and flush updated data from the handle into the target
    // of the handle. The target is set via WriteHandle::SetTarget.
    return buffer->writeHandle->DeserializeDataUpdate(
        writeDataUpdateInfo, static_cast<size_t>(writeDataUpdateInfoLength),
        static_cast<size_t>(offset), static_cast<size_t>(size));
}

void Server::OnBufferMapAsyncCallback(MapUserdata* data, WGPUBufferMapAsyncStatus status) {
    // Skip sending the callback if the buffer has already been destroyed.
    auto* bufferData = BufferObjects().Get(data->buffer.id);
    if (bufferData == nullptr || bufferData->generation != data->buffer.generation) {
        return;
    }

    bool isRead = data->mode & WGPUMapMode_Read;
    bool isSuccess = status == WGPUBufferMapAsyncStatus_Success;

    ReturnBufferMapAsyncCallbackCmd cmd;
    cmd.buffer = data->buffer;
    cmd.requestSerial = data->requestSerial;
    cmd.status = status;
    cmd.readDataUpdateInfoLength = 0;
    cmd.readDataUpdateInfo = nullptr;

    const void* readData = nullptr;
    if (isSuccess) {
        if (isRead) {
            // Get the serialization size of the message to initialize ReadHandle data.
            readData = mProcs.bufferGetConstMappedRange(data->bufferObj, data->offset, data->size);
            cmd.readDataUpdateInfoLength =
                bufferData->readHandle->SizeOfSerializeDataUpdate(data->offset, data->size);
        } else {
            ASSERT(data->mode & WGPUMapMode_Write);
            // The in-flight map request returned successfully.
            bufferData->mapWriteState = BufferMapWriteState::Mapped;
            // Set the target of the WriteHandle to the mapped buffer data.
            // writeHandle Target always refers to the buffer base address.
            // but we call getMappedRange exactly with the range of data that is potentially
            // modified (i.e. we don't want getMappedRange(0, wholeBufferSize) if only a
            // subset of the buffer is actually mapped) in case the implementation does some
            // range tracking.
            bufferData->writeHandle->SetTarget(static_cast<uint8_t*>(mProcs.bufferGetMappedRange(
                                                   data->bufferObj, data->offset, data->size)) -
                                               data->offset);
        }
    }

    SerializeCommand(cmd, cmd.readDataUpdateInfoLength, [&](SerializeBuffer* serializeBuffer) {
        if (isSuccess && isRead) {
            char* readHandleBuffer;
            WIRE_TRY(serializeBuffer->NextN(cmd.readDataUpdateInfoLength, &readHandleBuffer));
            // The in-flight map request returned successfully.
            bufferData->readHandle->SerializeDataUpdate(readData, data->offset, data->size,
                                                        readHandleBuffer);
        }
        return WireResult::Success;
    });
}

}  // namespace dawn::wire::server
