// Copyright 2020 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/QuerySet.h"

#include "dawn_native/Device.h"
#include "dawn_native/Features.h"
#include "dawn_native/ObjectType_autogen.h"
#include "dawn_native/ValidationUtils_autogen.h"

#include <set>

namespace dawn::native {

    namespace {

        class ErrorQuerySet final : public QuerySetBase {
          public:
            ErrorQuerySet(DeviceBase* device) : QuerySetBase(device, ObjectBase::kError) {
            }

          private:
            void DestroyImpl() override {
                UNREACHABLE();
            }
        };

    }  // anonymous namespace

    MaybeError ValidateQuerySetDescriptor(DeviceBase* device,
                                          const QuerySetDescriptor* descriptor) {
        DAWN_INVALID_IF(descriptor->nextInChain != nullptr, "nextInChain must be nullptr");

        DAWN_TRY(ValidateQueryType(descriptor->type));

        DAWN_INVALID_IF(descriptor->count > kMaxQueryCount,
                        "Query count (%u) exceeds the maximum query count (%u).", descriptor->count,
                        kMaxQueryCount);

        switch (descriptor->type) {
            case wgpu::QueryType::Occlusion:
                DAWN_INVALID_IF(descriptor->pipelineStatisticsCount != 0,
                                "Pipeline statistics specified for a query of type %s.",
                                descriptor->type);
                break;

            case wgpu::QueryType::PipelineStatistics: {
                // TODO(crbug.com/1177506): Pipeline statistics query is not fully implemented.
                // Disallow it as unsafe until the implementaion is completed.
                DAWN_INVALID_IF(device->IsToggleEnabled(Toggle::DisallowUnsafeAPIs),
                                "Pipeline statistics queries are disallowed because they are not "
                                "fully implemented");

                DAWN_INVALID_IF(
                    !device->IsFeatureEnabled(Feature::PipelineStatisticsQuery),
                    "Pipeline statistics query set created without the feature being enabled.");

                DAWN_INVALID_IF(descriptor->pipelineStatisticsCount == 0,
                                "Pipeline statistics query set created with 0 statistics.");

                std::set<wgpu::PipelineStatisticName> pipelineStatisticsSet;
                for (uint32_t i = 0; i < descriptor->pipelineStatisticsCount; i++) {
                    DAWN_TRY(ValidatePipelineStatisticName(descriptor->pipelineStatistics[i]));

                    auto [_, inserted] =
                        pipelineStatisticsSet.insert((descriptor->pipelineStatistics[i]));
                    DAWN_INVALID_IF(!inserted, "Statistic %s is specified more than once.",
                                    descriptor->pipelineStatistics[i]);
                }
            } break;

            case wgpu::QueryType::Timestamp:
                DAWN_INVALID_IF(device->IsToggleEnabled(Toggle::DisallowUnsafeAPIs),
                                "Timestamp queries are disallowed because they may expose precise "
                                "timing information.");

                DAWN_INVALID_IF(!device->IsFeatureEnabled(Feature::TimestampQuery),
                                "Timestamp query set created without the feature being enabled.");

                DAWN_INVALID_IF(descriptor->pipelineStatisticsCount != 0,
                                "Pipeline statistics specified for a query of type %s.",
                                descriptor->type);
                break;

            default:
                break;
        }

        return {};
    }

    QuerySetBase::QuerySetBase(DeviceBase* device, const QuerySetDescriptor* descriptor)
        : ApiObjectBase(device, descriptor->label),
          mQueryType(descriptor->type),
          mQueryCount(descriptor->count),
          mState(QuerySetState::Available) {
        for (uint32_t i = 0; i < descriptor->pipelineStatisticsCount; i++) {
            mPipelineStatistics.push_back(descriptor->pipelineStatistics[i]);
        }

        mQueryAvailability.resize(descriptor->count);
        TrackInDevice();
    }

    QuerySetBase::QuerySetBase(DeviceBase* device) : ApiObjectBase(device, kLabelNotImplemented) {
        TrackInDevice();
    }

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

    QuerySetBase::~QuerySetBase() {
        // Uninitialized or already destroyed
        ASSERT(mState == QuerySetState::Unavailable || mState == QuerySetState::Destroyed);
    }

    void QuerySetBase::DestroyImpl() {
        mState = QuerySetState::Destroyed;
    }

    // static
    QuerySetBase* QuerySetBase::MakeError(DeviceBase* device) {
        return new ErrorQuerySet(device);
    }

    ObjectType QuerySetBase::GetType() const {
        return ObjectType::QuerySet;
    }

    wgpu::QueryType QuerySetBase::GetQueryType() const {
        return mQueryType;
    }

    uint32_t QuerySetBase::GetQueryCount() const {
        return mQueryCount;
    }

    const std::vector<wgpu::PipelineStatisticName>& QuerySetBase::GetPipelineStatistics() const {
        return mPipelineStatistics;
    }

    const std::vector<bool>& QuerySetBase::GetQueryAvailability() const {
        return mQueryAvailability;
    }

    void QuerySetBase::SetQueryAvailability(uint32_t index, bool available) {
        mQueryAvailability[index] = available;
    }

    MaybeError QuerySetBase::ValidateCanUseInSubmitNow() const {
        ASSERT(!IsError());
        DAWN_INVALID_IF(mState == QuerySetState::Destroyed, "%s used while destroyed.", this);
        return {};
    }

    void QuerySetBase::APIDestroy() {
        if (GetDevice()->ConsumedError(ValidateDestroy())) {
            return;
        }
        Destroy();
    }

    MaybeError QuerySetBase::ValidateDestroy() const {
        DAWN_TRY(GetDevice()->ValidateObject(this));
        return {};
    }

}  // namespace dawn::native
