// 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.

#ifndef DAWNNATIVE_INSTANCE_H_
#define DAWNNATIVE_INSTANCE_H_

#include "common/RefCounted.h"
#include "common/ityp_bitset.h"
#include "dawn_native/Adapter.h"
#include "dawn_native/BackendConnection.h"
#include "dawn_native/Features.h"
#include "dawn_native/Toggles.h"
#include "dawn_native/dawn_platform.h"

#include <array>
#include <memory>
#include <unordered_map>
#include <vector>

namespace dawn::platform {
    class Platform;
}  // namespace dawn::platform

namespace dawn::native {

    class Surface;
    class XlibXcbFunctions;

    using BackendsBitset = ityp::bitset<wgpu::BackendType, kEnumCount<wgpu::BackendType>>;

    // This is called InstanceBase for consistency across the frontend, even if the backends don't
    // specialize this class.
    class InstanceBase final : public RefCounted {
      public:
        static InstanceBase* Create(const InstanceDescriptor* descriptor = nullptr);

        void APIRequestAdapter(const RequestAdapterOptions* options,
                               WGPURequestAdapterCallback callback,
                               void* userdata);

        void DiscoverDefaultAdapters();
        bool DiscoverAdapters(const AdapterDiscoveryOptionsBase* options);

        const std::vector<Ref<AdapterBase>>& GetAdapters() const;

        // Used to handle error that happen up to device creation.
        bool ConsumedError(MaybeError maybeError);

        // Used to query the details of a toggle. Return nullptr if toggleName is not a valid name
        // of a toggle supported in Dawn.
        const ToggleInfo* GetToggleInfo(const char* toggleName);
        Toggle ToggleNameToEnum(const char* toggleName);

        // Used to query the details of an feature. Return nullptr if featureName is not a valid
        // name of an feature supported in Dawn.
        const FeatureInfo* GetFeatureInfo(wgpu::FeatureName feature);

        bool IsBackendValidationEnabled() const;
        void SetBackendValidationLevel(BackendValidationLevel level);
        BackendValidationLevel GetBackendValidationLevel() const;

        void EnableBeginCaptureOnStartup(bool beginCaptureOnStartup);
        bool IsBeginCaptureOnStartupEnabled() const;

        void SetPlatform(dawn::platform::Platform* platform);
        dawn::platform::Platform* GetPlatform();

        // Get backend-independent libraries that need to be loaded dynamically.
        const XlibXcbFunctions* GetOrCreateXlibXcbFunctions();

        // Dawn API
        Surface* APICreateSurface(const SurfaceDescriptor* descriptor);

      private:
        InstanceBase() = default;
        ~InstanceBase() = default;

        InstanceBase(const InstanceBase& other) = delete;
        InstanceBase& operator=(const InstanceBase& other) = delete;

        bool Initialize(const InstanceDescriptor* descriptor);

        // Lazily creates connections to all backends that have been compiled.
        void EnsureBackendConnection(wgpu::BackendType backendType);

        MaybeError DiscoverAdaptersInternal(const AdapterDiscoveryOptionsBase* options);

        ResultOrError<Ref<AdapterBase>> RequestAdapterInternal(
            const RequestAdapterOptions* options);

        BackendsBitset mBackendsConnected;

        bool mDiscoveredDefaultAdapters = false;

        bool mBeginCaptureOnStartup = false;
        BackendValidationLevel mBackendValidationLevel = BackendValidationLevel::Disabled;

        dawn::platform::Platform* mPlatform = nullptr;
        std::unique_ptr<dawn::platform::Platform> mDefaultPlatform;

        std::vector<std::unique_ptr<BackendConnection>> mBackends;
        std::vector<Ref<AdapterBase>> mAdapters;

        FeaturesInfo mFeaturesInfo;
        TogglesInfo mTogglesInfo;

#if defined(DAWN_USE_X11)
        std::unique_ptr<XlibXcbFunctions> mXlibXcbFunctions;
#endif  // defined(DAWN_USE_X11)
    };

}  // namespace dawn::native

#endif  // DAWNNATIVE_INSTANCE_H_
