// Copyright 2021 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/dawn_proc.h"
#include "dawn/native/DawnNative.h"
#include "dawn/utils/SystemUtils.h"
#include "dawn/utils/WGPUHelpers.h"
#include "tests/MockCallback.h"

#include <gtest/gtest.h>

namespace {

    using namespace testing;

    class DeviceCreationTest : public testing::Test {
      protected:
        void SetUp() override {
            dawnProcSetProcs(&dawn::native::GetProcs());

            instance = std::make_unique<dawn::native::Instance>();
            instance->DiscoverDefaultAdapters();
            for (dawn::native::Adapter& nativeAdapter : instance->GetAdapters()) {
                wgpu::AdapterProperties properties;
                nativeAdapter.GetProperties(&properties);

                if (properties.backendType == wgpu::BackendType::Null) {
                    adapter = wgpu::Adapter(nativeAdapter.Get());
                    break;
                }
            }
            ASSERT_NE(adapter, nullptr);
        }

        void TearDown() override {
            adapter = nullptr;
            instance = nullptr;
            dawnProcSetProcs(nullptr);
        }

        std::unique_ptr<dawn::native::Instance> instance;
        wgpu::Adapter adapter;
    };

    // Test successful call to CreateDevice with no descriptor
    TEST_F(DeviceCreationTest, CreateDeviceNoDescriptorSuccess) {
        wgpu::Device device = adapter.CreateDevice();
        EXPECT_NE(device, nullptr);
    }

    // Test successful call to CreateDevice with descriptor.
    TEST_F(DeviceCreationTest, CreateDeviceSuccess) {
        wgpu::DeviceDescriptor desc = {};
        wgpu::Device device = adapter.CreateDevice(&desc);
        EXPECT_NE(device, nullptr);
    }

    // Test successful call to CreateDevice with toggle descriptor.
    TEST_F(DeviceCreationTest, CreateDeviceWithTogglesSuccess) {
        wgpu::DeviceDescriptor desc = {};
        wgpu::DawnTogglesDeviceDescriptor togglesDesc = {};
        desc.nextInChain = &togglesDesc;

        const char* toggle = "skip_validation";
        togglesDesc.forceEnabledToggles = &toggle;
        togglesDesc.forceEnabledTogglesCount = 1;

        wgpu::Device device = adapter.CreateDevice(&desc);
        EXPECT_NE(device, nullptr);

        auto toggles = dawn::native::GetTogglesUsed(device.Get());
        EXPECT_THAT(toggles, testing::Contains(testing::StrEq(toggle)));
    }

    // Test successful call to RequestDevice with descriptor
    TEST_F(DeviceCreationTest, RequestDeviceSuccess) {
        WGPUDevice cDevice;
        {
            MockCallback<WGPURequestDeviceCallback> cb;
            EXPECT_CALL(cb, Call(WGPURequestDeviceStatus_Success, NotNull(), nullptr, this))
                .WillOnce(SaveArg<1>(&cDevice));

            wgpu::DeviceDescriptor desc = {};
            adapter.RequestDevice(&desc, cb.Callback(), cb.MakeUserdata(this));
        }

        wgpu::Device device = wgpu::Device::Acquire(cDevice);
        EXPECT_NE(device, nullptr);
    }

    // Test successful call to RequestDevice with a null descriptor
    TEST_F(DeviceCreationTest, RequestDeviceNullDescriptorSuccess) {
        WGPUDevice cDevice;
        {
            MockCallback<WGPURequestDeviceCallback> cb;
            EXPECT_CALL(cb, Call(WGPURequestDeviceStatus_Success, NotNull(), nullptr, this))
                .WillOnce(SaveArg<1>(&cDevice));

            adapter.RequestDevice(nullptr, cb.Callback(), cb.MakeUserdata(this));
        }

        wgpu::Device device = wgpu::Device::Acquire(cDevice);
        EXPECT_NE(device, nullptr);
    }

    // Test failing call to RequestDevice with invalid feature
    TEST_F(DeviceCreationTest, RequestDeviceFailure) {
        MockCallback<WGPURequestDeviceCallback> cb;
        EXPECT_CALL(cb, Call(WGPURequestDeviceStatus_Error, nullptr, NotNull(), this)).Times(1);

        wgpu::DeviceDescriptor desc = {};
        wgpu::FeatureName invalidFeature = static_cast<wgpu::FeatureName>(WGPUFeatureName_Force32);
        desc.requiredFeatures = &invalidFeature;
        desc.requiredFeaturesCount = 1;

        adapter.RequestDevice(&desc, cb.Callback(), cb.MakeUserdata(this));
    }

}  // anonymous namespace
