// 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 "common/Assert.h"
#include "dawn_wire/BufferConsumer_impl.h"
#include "dawn_wire/WireCmd_autogen.h"
#include "dawn_wire/server/Server.h"

#include <memory>

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
