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