// 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<std::unique_ptr<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);

        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<std::unique_ptr<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_
