// Copyright 2018 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_native/Fence.h"

#include "common/Assert.h"
#include "dawn_native/Device.h"
#include "dawn_native/Queue.h"
#include "dawn_native/ValidationUtils_autogen.h"

#include <utility>

namespace dawn_native {

    struct FenceInFlight : QueueBase::TaskInFlight {
        FenceInFlight(Ref<Fence> fence, FenceAPISerial value)
            : fence(std::move(fence)), value(value) {
        }
        void Finish() override {
            fence->SetCompletedValue(value, WGPUFenceCompletionStatus_Success);
        }
        void HandleDeviceLoss() override {
            fence->SetCompletedValue(value, WGPUFenceCompletionStatus_DeviceLost);
        }
        ~FenceInFlight() override = default;

      private:
        Ref<Fence> fence;
        FenceAPISerial value;
    };

    MaybeError ValidateFenceDescriptor(const FenceDescriptor* descriptor) {
        if (descriptor->nextInChain != nullptr) {
            return DAWN_VALIDATION_ERROR("nextInChain must be nullptr");
        }

        return {};
    }

    // Fence

    Fence::Fence(QueueBase* queue, const FenceDescriptor* descriptor)
        : ObjectBase(queue->GetDevice()),
          mSignalValue(descriptor->initialValue),
          mCompletedValue(descriptor->initialValue),
          mQueue(queue) {
    }

    Fence::Fence(DeviceBase* device, ObjectBase::ErrorTag tag) : ObjectBase(device, tag) {
    }

    Fence::~Fence() {
        for (auto& request : mRequests.IterateAll()) {
            ASSERT(!IsError());
            request.completionCallback(WGPUFenceCompletionStatus_Unknown, request.userdata);
        }
        mRequests.Clear();
    }

    // static
    Fence* Fence::MakeError(DeviceBase* device) {
        return new Fence(device, ObjectBase::kError);
    }

    uint64_t Fence::APIGetCompletedValue() const {
        if (IsError()) {
            return 0;
        }
        return uint64_t(mCompletedValue);
    }

    void Fence::APIOnCompletion(uint64_t apiValue,
                                wgpu::FenceOnCompletionCallback callback,
                                void* userdata) {
        FenceAPISerial value(apiValue);

        WGPUFenceCompletionStatus status;
        if (GetDevice()->ConsumedError(ValidateOnCompletion(value, &status))) {
            callback(status, userdata);
            return;
        }
        ASSERT(!IsError());

        if (value <= mCompletedValue) {
            callback(WGPUFenceCompletionStatus_Success, userdata);
            return;
        }

        OnCompletionData request;
        request.completionCallback = callback;
        request.userdata = userdata;
        mRequests.Enqueue(std::move(request), value);
    }

    FenceAPISerial Fence::GetSignaledValue() const {
        ASSERT(!IsError());
        return mSignalValue;
    }

    const QueueBase* Fence::GetQueue() const {
        ASSERT(!IsError());
        return mQueue.Get();
    }

    void Fence::SetSignaledValue(FenceAPISerial signalValue) {
        ASSERT(!IsError());
        ASSERT(signalValue > mSignalValue);
        mSignalValue = signalValue;
    }

    void Fence::SetCompletedValue(FenceAPISerial completedValue, WGPUFenceCompletionStatus status) {
        ASSERT(!IsError());
        ASSERT(completedValue <= mSignalValue);
        ASSERT(completedValue > mCompletedValue);
        mCompletedValue = completedValue;

        for (auto& request : mRequests.IterateUpTo(mCompletedValue)) {
            request.completionCallback(status, request.userdata);
        }
        mRequests.ClearUpTo(mCompletedValue);
    }

    void Fence::UpdateFenceOnComplete(Fence* fence, FenceAPISerial value) {
        std::unique_ptr<FenceInFlight> fenceInFlight =
            std::make_unique<FenceInFlight>(fence, value);

        // TODO: use GetLastSubmittedCommandSerial in the future for perforamnce
        GetDevice()->GetQueue()->TrackTask(std::move(fenceInFlight),
                                           GetDevice()->GetPendingCommandSerial());
    }

    MaybeError Fence::ValidateOnCompletion(FenceAPISerial value,
                                           WGPUFenceCompletionStatus* status) const {
        *status = WGPUFenceCompletionStatus_DeviceLost;
        DAWN_TRY(GetDevice()->ValidateIsAlive());

        *status = WGPUFenceCompletionStatus_Error;
        DAWN_TRY(GetDevice()->ValidateObject(this));

        if (value > mSignalValue) {
            return DAWN_VALIDATION_ERROR("Value greater than fence signaled value");
        }

        *status = WGPUFenceCompletionStatus_Success;
        return {};
    }

}  // namespace dawn_native
