// Copyright 2020 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 "dawn_wire/client/Queue.h"

#include "dawn_wire/client/Client.h"
#include "dawn_wire/client/Device.h"

namespace dawn_wire { namespace client {

    Queue::~Queue() {
        ClearAllCallbacks(WGPUQueueWorkDoneStatus_Unknown);
    }

    bool Queue::OnWorkDoneCallback(uint64_t requestSerial, WGPUQueueWorkDoneStatus status) {
        OnWorkDoneData request;
        if (!mOnWorkDoneRequests.Acquire(requestSerial, &request)) {
            return false;
        }

        request.callback(status, request.userdata);
        return true;
    }

    void Queue::OnSubmittedWorkDone(uint64_t signalValue,
                                    WGPUQueueWorkDoneCallback callback,
                                    void* userdata) {
        if (client->IsDisconnected()) {
            callback(WGPUQueueWorkDoneStatus_DeviceLost, userdata);
            return;
        }

        uint64_t serial = mOnWorkDoneRequests.Add({callback, userdata});

        QueueOnSubmittedWorkDoneCmd cmd;
        cmd.queueId = this->id;
        cmd.signalValue = signalValue;
        cmd.requestSerial = serial;

        client->SerializeCommand(cmd);
    }

    void Queue::WriteBuffer(WGPUBuffer cBuffer,
                            uint64_t bufferOffset,
                            const void* data,
                            size_t size) {
        Buffer* buffer = FromAPI(cBuffer);

        QueueWriteBufferInternalCmd cmd;
        cmd.queueId = id;
        cmd.bufferId = buffer->id;
        cmd.bufferOffset = bufferOffset;
        cmd.data = static_cast<const uint8_t*>(data);
        cmd.size = size;

        client->SerializeCommand(cmd);
    }

    void Queue::WriteTexture(const WGPUImageCopyTexture* destination,
                             const void* data,
                             size_t dataSize,
                             const WGPUTextureDataLayout* dataLayout,
                             const WGPUExtent3D* writeSize) {
        QueueWriteTextureInternalCmd cmd;
        cmd.queueId = id;
        cmd.destination = destination;
        cmd.data = static_cast<const uint8_t*>(data);
        cmd.dataSize = dataSize;
        cmd.dataLayout = dataLayout;
        cmd.writeSize = writeSize;

        client->SerializeCommand(cmd);
    }

    void Queue::CancelCallbacksForDisconnect() {
        ClearAllCallbacks(WGPUQueueWorkDoneStatus_DeviceLost);
    }

    void Queue::ClearAllCallbacks(WGPUQueueWorkDoneStatus status) {
        mOnWorkDoneRequests.CloseAll([status](OnWorkDoneData* request) {
            if (request->callback != nullptr) {
                request->callback(status, request->userdata);
            }
        });
    }

}}  // namespace dawn_wire::client
