// Copyright 2019 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_ENCODINGCONTEXT_H_
#define DAWNNATIVE_ENCODINGCONTEXT_H_

#include "dawn_native/CommandAllocator.h"
#include "dawn_native/Error.h"
#include "dawn_native/ErrorData.h"
#include "dawn_native/IndirectDrawMetadata.h"
#include "dawn_native/PassResourceUsageTracker.h"
#include "dawn_native/dawn_platform.h"

#include <string>

namespace dawn::native {

    class CommandEncoder;
    class DeviceBase;
    class ApiObjectBase;

    // Base class for allocating/iterating commands.
    // It performs error tracking as well as encoding state for render/compute passes.
    class EncodingContext {
      public:
        EncodingContext(DeviceBase* device, const ApiObjectBase* initialEncoder);
        ~EncodingContext();

        // Marks the encoding context as destroyed so that any future encodes will fail, and all
        // encoded commands are released.
        void Destroy();

        CommandIterator AcquireCommands();
        CommandIterator* GetIterator();

        // Functions to handle encoder errors
        void HandleError(std::unique_ptr<ErrorData> error);

        inline bool ConsumedError(MaybeError maybeError) {
            if (DAWN_UNLIKELY(maybeError.IsError())) {
                HandleError(maybeError.AcquireError());
                return true;
            }
            return false;
        }

        template <typename... Args>
        inline bool ConsumedError(MaybeError maybeError,
                                  const char* formatStr,
                                  const Args&... args) {
            if (DAWN_UNLIKELY(maybeError.IsError())) {
                std::unique_ptr<ErrorData> error = maybeError.AcquireError();
                if (error->GetType() == InternalErrorType::Validation) {
                    std::string out;
                    absl::UntypedFormatSpec format(formatStr);
                    if (absl::FormatUntyped(&out, format, {absl::FormatArg(args)...})) {
                        error->AppendContext(std::move(out));
                    } else {
                        error->AppendContext(absl::StrFormat(
                            "[Failed to format error message: \"%s\"].", formatStr));
                    }
                }
                HandleError(std::move(error));
                return true;
            }
            return false;
        }

        inline bool CheckCurrentEncoder(const ApiObjectBase* encoder) {
            if (DAWN_UNLIKELY(encoder != mCurrentEncoder)) {
                if (mDestroyed) {
                    HandleError(
                        DAWN_FORMAT_VALIDATION_ERROR("Recording in a destroyed %s.", encoder));
                } else if (mCurrentEncoder != mTopLevelEncoder) {
                    // The top level encoder was used when a pass encoder was current.
                    HandleError(DAWN_FORMAT_VALIDATION_ERROR(
                        "Command cannot be recorded while %s is active.", mCurrentEncoder));
                } else {
                    HandleError(DAWN_FORMAT_VALIDATION_ERROR(
                        "Recording in an error or already ended %s.", encoder));
                }
                return false;
            }
            return true;
        }

        template <typename EncodeFunction>
        inline bool TryEncode(const ApiObjectBase* encoder, EncodeFunction&& encodeFunction) {
            if (!CheckCurrentEncoder(encoder)) {
                return false;
            }
            ASSERT(!mWasMovedToIterator);
            return !ConsumedError(encodeFunction(&mPendingCommands));
        }

        template <typename EncodeFunction, typename... Args>
        inline bool TryEncode(const ApiObjectBase* encoder,
                              EncodeFunction&& encodeFunction,
                              const char* formatStr,
                              const Args&... args) {
            if (!CheckCurrentEncoder(encoder)) {
                return false;
            }
            ASSERT(!mWasMovedToIterator);
            return !ConsumedError(encodeFunction(&mPendingCommands), formatStr, args...);
        }

        // Must be called prior to encoding a BeginRenderPassCmd. Note that it's OK to call this
        // and then not actually call EnterPass+ExitRenderPass, for example if some other pass setup
        // failed validation before the BeginRenderPassCmd could be encoded.
        void WillBeginRenderPass();

        // Functions to set current encoder state
        void EnterPass(const ApiObjectBase* passEncoder);
        MaybeError ExitRenderPass(const ApiObjectBase* passEncoder,
                                  RenderPassResourceUsageTracker usageTracker,
                                  CommandEncoder* commandEncoder,
                                  IndirectDrawMetadata indirectDrawMetadata);
        void ExitComputePass(const ApiObjectBase* passEncoder, ComputePassResourceUsage usages);
        MaybeError Finish();

        // Called when a pass encoder is deleted. Provides an opportunity to clean up if it's the
        // mCurrentEncoder.
        void EnsurePassExited(const ApiObjectBase* passEncoder);

        const RenderPassUsages& GetRenderPassUsages() const;
        const ComputePassUsages& GetComputePassUsages() const;
        RenderPassUsages AcquireRenderPassUsages();
        ComputePassUsages AcquireComputePassUsages();

        void PushDebugGroupLabel(const char* groupLabel);
        void PopDebugGroupLabel();

      private:
        void CommitCommands(CommandAllocator allocator);

        bool IsFinished() const;
        void MoveToIterator();

        DeviceBase* mDevice;

        // There can only be two levels of encoders. Top-level and render/compute pass.
        // The top level encoder is the encoder the EncodingContext is created with.
        // It doubles as flag to check if encoding has been Finished.
        const ApiObjectBase* mTopLevelEncoder;
        // The current encoder must be the same as the encoder provided to TryEncode,
        // otherwise an error is produced. It may be nullptr if the EncodingContext is an error.
        // The current encoder changes with Enter/ExitPass which should be called by
        // CommandEncoder::Begin/EndPass.
        const ApiObjectBase* mCurrentEncoder;

        RenderPassUsages mRenderPassUsages;
        bool mWereRenderPassUsagesAcquired = false;
        ComputePassUsages mComputePassUsages;
        bool mWereComputePassUsagesAcquired = false;

        CommandAllocator mPendingCommands;

        std::vector<CommandAllocator> mAllocators;
        CommandIterator mIterator;
        bool mWasMovedToIterator = false;
        bool mWereCommandsAcquired = false;
        bool mDestroyed = false;

        std::unique_ptr<ErrorData> mError;
        std::vector<std::string> mDebugGroupLabels;
    };

}  // namespace dawn::native

#endif  // DAWNNATIVE_ENCODINGCONTEXT_H_
