// Copyright 2019 The Dawn & Tint Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived from
//    this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "dawn/wire/server/Server.h"

#include "dawn/wire/WireServer.h"

namespace dawn::wire::server {

CallbackUserdata::CallbackUserdata(const std::weak_ptr<Server>& server,
                                   std::shared_ptr<const DawnProcTable>& procs)
    : server(server), procs(procs) {}

// static
std::shared_ptr<Server> Server::Create(const DawnProcTable& procs,
                                       CommandSerializer* serializer,
                                       MemoryTransferService* memoryTransferService,
                                       bool useSpontaneousCallbacks) {
    auto server = std::shared_ptr<Server>(
        new Server(procs, serializer, memoryTransferService, useSpontaneousCallbacks));
    server->mSelf = server;
    return server;
}

Server::Server(const DawnProcTable& procs,
               CommandSerializer* serializer,
               MemoryTransferService* memoryTransferService,
               bool useSpontaneousCallbacks)
    : ServerBase(procs),
      mSerializer(serializer),
      mMemoryTransferService(memoryTransferService),
      mUseSpontaneousCallbacks(useSpontaneousCallbacks) {
    if (mMemoryTransferService == nullptr) {
        // If a MemoryTransferService is not provided, fallback to inline memory.
        mOwnedMemoryTransferService = CreateInlineMemoryTransferService();
        mMemoryTransferService = mOwnedMemoryTransferService.get();
    }
}

Server::~Server() {
    // Un-set the error and lost callbacks since we cannot forward them
    // after the server has been destroyed.
    for (WGPUDevice device : GetAllDeviceHandles()) {
        ClearDeviceCallbacks(device);
    }
    DestroyAllObjects();
}

WireResult Server::InjectBuffer(WGPUBuffer buffer,
                                const Handle& handle,
                                const Handle& deviceHandle) {
    DAWN_ASSERT(buffer != nullptr);
    Known<WGPUDevice> device;
    WIRE_TRY(Get(deviceHandle.id, &device));
    if (device->generation != deviceHandle.generation) {
        return WireResult::FatalError;
    }

    Reserved<WGPUBuffer> data;
    WIRE_TRY(Allocate(&data, handle));

    data->handle = buffer;
    data->generation = handle.generation;
    data->state = AllocationState::Allocated;

    // The Buffer is externally owned so it shouldn't be destroyed when we receive a destroy
    // message from the client. Add a reference to counterbalance the eventual release.
    mProcs->bufferAddRef(buffer);

    return WireResult::Success;
}

WireResult Server::InjectTexture(WGPUTexture texture,
                                 const Handle& handle,
                                 const Handle& deviceHandle) {
    DAWN_ASSERT(texture != nullptr);
    Known<WGPUDevice> device;
    WIRE_TRY(Get(deviceHandle.id, &device));
    if (device->generation != deviceHandle.generation) {
        return WireResult::FatalError;
    }

    Reserved<WGPUTexture> data;
    WIRE_TRY(Allocate(&data, handle));

    data->handle = texture;
    data->generation = handle.generation;
    data->state = AllocationState::Allocated;

    // The texture is externally owned so it shouldn't be destroyed when we receive a destroy
    // message from the client. Add a reference to counterbalance the eventual release.
    mProcs->textureAddRef(texture);

    return WireResult::Success;
}

WireResult Server::InjectSurface(WGPUSurface surface,
                                 const Handle& handle,
                                 const Handle& instanceHandle) {
    DAWN_ASSERT(surface != nullptr);
    Known<WGPUInstance> instance;
    WIRE_TRY(Get(instanceHandle.id, &instance));
    if (instance->generation != instanceHandle.generation) {
        return WireResult::FatalError;
    }

    Reserved<WGPUSurface> data;
    WIRE_TRY(Allocate(&data, handle));

    data->handle = surface;
    data->generation = handle.generation;
    data->state = AllocationState::Allocated;

    // The surface is externally owned so it shouldn't be destroyed when we receive a destroy
    // message from the client. Add a reference to counterbalance the eventual release.
    mProcs->surfaceAddRef(surface);

    return WireResult::Success;
}

WireResult Server::InjectInstance(WGPUInstance instance, const Handle& handle) {
    DAWN_ASSERT(instance != nullptr);
    Reserved<WGPUInstance> data;
    WIRE_TRY(Allocate(&data, handle));

    data->handle = instance;
    data->generation = handle.generation;
    data->state = AllocationState::Allocated;

    // The instance is externally owned so it shouldn't be destroyed when we receive a destroy
    // message from the client. Add a reference to counterbalance the eventual release.
    mProcs->instanceAddRef(instance);

    return WireResult::Success;
}

WGPUDevice Server::GetDevice(uint32_t id, uint32_t generation) {
    Known<WGPUDevice> device;
    if (Get(id, &device) != WireResult::Success || device->generation != generation) {
        return nullptr;
    }
    return device->handle;
}

void Server::Flush() {
    if (mUseSpontaneousCallbacks) {
        mSerializer->Flush();
    }
}

namespace {
static constexpr WGPULoggingCallbackInfo kEmptyLoggingCallbackInfo = {nullptr, nullptr, nullptr,
                                                                      nullptr};
}  // namespace

void Server::SetForwardingDeviceCallbacks(Known<WGPUDevice> device) {
    // Note: these callbacks are manually inlined here since they do not acquire and
    // free their userdata. Also unlike other callbacks, these are cleared and unset when
    // the server is destroyed, so we don't need to check if the server is still alive
    // inside them.
    // Also, the device is special-cased in Server::DoUnregisterObject to call
    // ClearDeviceCallbacks. This ensures that callbacks will not fire after |deviceObject|
    // is freed.

    // Set callback to post warning and other information to client.
    mProcs->deviceSetLoggingCallback(
        device->handle, {nullptr,
                         [](WGPULoggingType type, WGPUStringView message, void* userdata, void*) {
                             DeviceInfo* info = static_cast<DeviceInfo*>(userdata);
                             info->server->OnLogging(info->self, type, message);
                             info->server->Flush();
                         },
                         device->info.get(), nullptr});
}

void Server::ClearDeviceCallbacks(WGPUDevice device) {
    // Un-set the logging callback since we cannot forward them after the server has been destroyed.
    mProcs->deviceSetLoggingCallback(device, kEmptyLoggingCallbackInfo);
}

}  // namespace dawn::wire::server
