// 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 SRC_DAWN_NATIVE_ENCODINGCONTEXT_H_
#define SRC_DAWN_NATIVE_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  // SRC_DAWN_NATIVE_ENCODINGCONTEXT_H_
