// 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 "tests/MockCallback.h"
#include "tests/unittests/wire/WireTest.h"

#include "dawn_wire/WireClient.h"
#include "dawn_wire/WireServer.h"

#include <webgpu/webgpu_cpp.h>
#include <unordered_set>
#include <vector>

namespace {

    using namespace testing;
    using namespace dawn_wire;

    class WireInstanceBasicTest : public WireTest {};
    class WireInstanceTests : public WireTest {
      protected:
        void SetUp() override {
            WireTest::SetUp();

            auto reservation = GetWireClient()->ReserveInstance();
            instance = wgpu::Instance::Acquire(reservation.instance);

            apiInstance = api.GetNewInstance();
            EXPECT_CALL(api, InstanceReference(apiInstance));
            EXPECT_TRUE(GetWireServer()->InjectInstance(apiInstance, reservation.id,
                                                        reservation.generation));
        }

        void TearDown() override {
            instance = nullptr;
            WireTest::TearDown();
        }

        wgpu::Instance instance;
        WGPUInstance apiInstance;
    };

    // Test that an Instance can be reserved and injected into the wire.
    TEST_F(WireInstanceBasicTest, ReserveAndInject) {
        auto reservation = GetWireClient()->ReserveInstance();
        wgpu::Instance instance = wgpu::Instance::Acquire(reservation.instance);

        WGPUInstance apiInstance = api.GetNewInstance();
        EXPECT_CALL(api, InstanceReference(apiInstance));
        EXPECT_TRUE(
            GetWireServer()->InjectInstance(apiInstance, reservation.id, reservation.generation));

        instance = nullptr;

        EXPECT_CALL(api, InstanceRelease(apiInstance));
        FlushClient();
    }

    // Test that RequestAdapterOptions are passed from the client to the server.
    TEST_F(WireInstanceTests, RequestAdapterPassesOptions) {
        MockCallback<WGPURequestAdapterCallback> cb;
        auto* userdata = cb.MakeUserdata(this);

        for (wgpu::PowerPreference powerPreference :
             {wgpu::PowerPreference::LowPower, wgpu::PowerPreference::HighPerformance}) {
            wgpu::RequestAdapterOptions options = {};
            options.powerPreference = powerPreference;

            instance.RequestAdapter(&options, cb.Callback(), userdata);

            EXPECT_CALL(api, OnInstanceRequestAdapter(apiInstance, NotNull(), NotNull(), NotNull()))
                .WillOnce(WithArg<1>(Invoke([&](const WGPURequestAdapterOptions* apiOptions) {
                    EXPECT_EQ(apiOptions->powerPreference,
                              static_cast<WGPUPowerPreference>(options.powerPreference));
                    EXPECT_EQ(apiOptions->forceFallbackAdapter, options.forceFallbackAdapter);
                })));
            FlushClient();
        }

        // Delete the instance now, or it'll call the mock callback after it's deleted.
        instance = nullptr;
    }

    // Test that RequestAdapter forwards the adapter information to the client.
    TEST_F(WireInstanceTests, RequestAdapterSuccess) {
        wgpu::RequestAdapterOptions options = {};
        MockCallback<WGPURequestAdapterCallback> cb;
        auto* userdata = cb.MakeUserdata(this);
        instance.RequestAdapter(&options, cb.Callback(), userdata);

        wgpu::AdapterProperties fakeProperties = {};
        fakeProperties.vendorID = 0x134;
        fakeProperties.deviceID = 0x918;
        fakeProperties.name = "fake adapter";
        fakeProperties.driverDescription = "hello world";
        fakeProperties.backendType = wgpu::BackendType::D3D12;
        fakeProperties.adapterType = wgpu::AdapterType::IntegratedGPU;

        wgpu::SupportedLimits fakeLimits = {};
        fakeLimits.limits.maxTextureDimension1D = 433;
        fakeLimits.limits.maxVertexAttributes = 1243;

        std::initializer_list<wgpu::FeatureName> fakeFeatures = {
            wgpu::FeatureName::Depth32FloatStencil8,
            wgpu::FeatureName::TextureCompressionBC,
        };

        // Expect the server to receive the message. Then, mock a fake reply.
        WGPUAdapter apiAdapter = api.GetNewAdapter();
        EXPECT_CALL(api, OnInstanceRequestAdapter(apiInstance, NotNull(), NotNull(), NotNull()))
            .WillOnce(InvokeWithoutArgs([&]() {
                EXPECT_CALL(api, AdapterGetProperties(apiAdapter, NotNull()))
                    .WillOnce(SetArgPointee<1>(
                        *reinterpret_cast<WGPUAdapterProperties*>(&fakeProperties)));

                EXPECT_CALL(api, AdapterGetLimits(apiAdapter, NotNull()))
                    .WillOnce(WithArg<1>(Invoke([&](WGPUSupportedLimits* limits) {
                        *reinterpret_cast<wgpu::SupportedLimits*>(limits) = fakeLimits;
                        return true;
                    })));

                EXPECT_CALL(api, AdapterEnumerateFeatures(apiAdapter, nullptr))
                    .WillOnce(Return(fakeFeatures.size()));

                EXPECT_CALL(api, AdapterEnumerateFeatures(apiAdapter, NotNull()))
                    .WillOnce(WithArg<1>(Invoke([&](WGPUFeatureName* features) {
                        for (wgpu::FeatureName feature : fakeFeatures) {
                            *(features++) = static_cast<WGPUFeatureName>(feature);
                        }
                        return fakeFeatures.size();
                    })));
                api.CallInstanceRequestAdapterCallback(
                    apiInstance, WGPURequestAdapterStatus_Success, apiAdapter, nullptr);
            }));
        FlushClient();

        // Expect the callback in the client and all the adapter information to match.
        EXPECT_CALL(cb, Call(WGPURequestAdapterStatus_Success, NotNull(), nullptr, this))
            .WillOnce(WithArg<1>(Invoke([&](WGPUAdapter cAdapter) {
                wgpu::Adapter adapter = wgpu::Adapter::Acquire(cAdapter);

                wgpu::AdapterProperties properties;
                adapter.GetProperties(&properties);
                EXPECT_EQ(properties.vendorID, fakeProperties.vendorID);
                EXPECT_EQ(properties.deviceID, fakeProperties.deviceID);
                EXPECT_STREQ(properties.name, fakeProperties.name);
                EXPECT_STREQ(properties.driverDescription, fakeProperties.driverDescription);
                EXPECT_EQ(properties.backendType, fakeProperties.backendType);
                EXPECT_EQ(properties.adapterType, fakeProperties.adapterType);

                wgpu::SupportedLimits limits;
                EXPECT_TRUE(adapter.GetLimits(&limits));
                EXPECT_EQ(limits.limits.maxTextureDimension1D,
                          fakeLimits.limits.maxTextureDimension1D);
                EXPECT_EQ(limits.limits.maxVertexAttributes, fakeLimits.limits.maxVertexAttributes);

                std::vector<wgpu::FeatureName> features;
                features.resize(adapter.EnumerateFeatures(nullptr));
                ASSERT_EQ(features.size(), fakeFeatures.size());
                EXPECT_EQ(adapter.EnumerateFeatures(&features[0]), features.size());

                std::unordered_set<wgpu::FeatureName> featureSet(fakeFeatures);
                for (wgpu::FeatureName feature : features) {
                    EXPECT_EQ(featureSet.erase(feature), 1u);
                }
            })));
        FlushServer();
    }

    // Test that features returned by the implementation that aren't supported
    // in the wire are not exposed.
    TEST_F(WireInstanceTests, RequestAdapterWireLacksFeatureSupport) {
        wgpu::RequestAdapterOptions options = {};
        MockCallback<WGPURequestAdapterCallback> cb;
        auto* userdata = cb.MakeUserdata(this);
        instance.RequestAdapter(&options, cb.Callback(), userdata);

        std::initializer_list<wgpu::FeatureName> fakeFeatures = {
            wgpu::FeatureName::Depth24UnormStencil8,
            // Some value that is not a valid feature
            static_cast<wgpu::FeatureName>(-2),
        };

        // Expect the server to receive the message. Then, mock a fake reply.
        WGPUAdapter apiAdapter = api.GetNewAdapter();
        EXPECT_CALL(api, OnInstanceRequestAdapter(apiInstance, NotNull(), NotNull(), NotNull()))
            .WillOnce(InvokeWithoutArgs([&]() {
                EXPECT_CALL(api, AdapterGetProperties(apiAdapter, NotNull()))
                    .WillOnce(WithArg<1>(Invoke([&](WGPUAdapterProperties* properties) {
                        *properties = {};
                        properties->name = "";
                        properties->driverDescription = "";
                    })));

                EXPECT_CALL(api, AdapterGetLimits(apiAdapter, NotNull()))
                    .WillOnce(WithArg<1>(Invoke([&](WGPUSupportedLimits* limits) {
                        *limits = {};
                        return true;
                    })));

                EXPECT_CALL(api, AdapterEnumerateFeatures(apiAdapter, nullptr))
                    .WillOnce(Return(fakeFeatures.size()));

                EXPECT_CALL(api, AdapterEnumerateFeatures(apiAdapter, NotNull()))
                    .WillOnce(WithArg<1>(Invoke([&](WGPUFeatureName* features) {
                        for (wgpu::FeatureName feature : fakeFeatures) {
                            *(features++) = static_cast<WGPUFeatureName>(feature);
                        }
                        return fakeFeatures.size();
                    })));
                api.CallInstanceRequestAdapterCallback(
                    apiInstance, WGPURequestAdapterStatus_Success, apiAdapter, nullptr);
            }));
        FlushClient();

        // Expect the callback in the client and all the adapter information to match.
        EXPECT_CALL(cb, Call(WGPURequestAdapterStatus_Success, NotNull(), nullptr, this))
            .WillOnce(WithArg<1>(Invoke([&](WGPUAdapter cAdapter) {
                wgpu::Adapter adapter = wgpu::Adapter::Acquire(cAdapter);

                wgpu::FeatureName feature;
                ASSERT_EQ(adapter.EnumerateFeatures(nullptr), 1u);
                adapter.EnumerateFeatures(&feature);

                EXPECT_EQ(feature, wgpu::FeatureName::Depth24UnormStencil8);
            })));
        FlushServer();
    }

    // Test that RequestAdapter errors forward to the client.
    TEST_F(WireInstanceTests, RequestAdapterError) {
        wgpu::RequestAdapterOptions options = {};
        MockCallback<WGPURequestAdapterCallback> cb;
        auto* userdata = cb.MakeUserdata(this);
        instance.RequestAdapter(&options, cb.Callback(), userdata);

        // Expect the server to receive the message. Then, mock an error.
        EXPECT_CALL(api, OnInstanceRequestAdapter(apiInstance, NotNull(), NotNull(), NotNull()))
            .WillOnce(InvokeWithoutArgs([&]() {
                api.CallInstanceRequestAdapterCallback(apiInstance, WGPURequestAdapterStatus_Error,
                                                       nullptr, "Some error");
            }));
        FlushClient();

        // Expect the callback in the client.
        EXPECT_CALL(cb, Call(WGPURequestAdapterStatus_Error, nullptr, StrEq("Some error"), this))
            .Times(1);
        FlushServer();
    }

    // Test that RequestAdapter receives unknown status if the instance is deleted
    // before the callback happens.
    TEST_F(WireInstanceTests, RequestAdapterInstanceDestroyedBeforeCallback) {
        wgpu::RequestAdapterOptions options = {};
        MockCallback<WGPURequestAdapterCallback> cb;
        auto* userdata = cb.MakeUserdata(this);
        instance.RequestAdapter(&options, cb.Callback(), userdata);

        EXPECT_CALL(cb, Call(WGPURequestAdapterStatus_Unknown, nullptr, NotNull(), this)).Times(1);
        instance = nullptr;
    }

    // Test that RequestAdapter receives unknown status if the wire is disconnected
    // before the callback happens.
    TEST_F(WireInstanceTests, RequestAdapterWireDisconnectBeforeCallback) {
        wgpu::RequestAdapterOptions options = {};
        MockCallback<WGPURequestAdapterCallback> cb;
        auto* userdata = cb.MakeUserdata(this);
        instance.RequestAdapter(&options, cb.Callback(), userdata);

        EXPECT_CALL(cb, Call(WGPURequestAdapterStatus_Unknown, nullptr, NotNull(), this)).Times(1);
        GetWireClient()->Disconnect();
    }

}  // anonymous namespace