// 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 { namespace 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;

        if (offset64 > std::numeric_limits<size_t>::max() ||
            size64 > std::numeric_limits<size_t>::max()) {
            OnBufferMapAsyncCallback(WGPUBufferMapAsyncStatus_Error, userdata.get());
            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<decltype(
                &Server::OnBufferMapAsyncCallback)>::Func<&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(WGPUBufferMapAsyncStatus status, MapUserdata* data) {
        // 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
