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

        // 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(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
