// Copyright 2023 The Tint 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_TINT_LANG_WGSL_PROGRAM_CLONE_CONTEXT_H_
#define SRC_TINT_LANG_WGSL_PROGRAM_CLONE_CONTEXT_H_

#include <utility>

#include "src/tint/lang/wgsl/ast/clone_context.h"
#include "src/tint/lang/wgsl/program/program.h"
#include "src/tint/lang/wgsl/program/program_builder.h"

// Forward declarations
namespace tint::program {

/// CloneContext holds the state used while cloning Programs.
class CloneContext {
  public:
    /// SymbolTransform is a function that takes a symbol and returns a new
    /// symbol.
    using SymbolTransform = std::function<Symbol(Symbol)>;

    /// Constructor for cloning objects from `from` into `to`.
    /// @param to the target Builder to clone into
    /// @param from the source Program to clone from
    /// @param auto_clone_symbols clone all symbols in `from` before returning
    CloneContext(ProgramBuilder* to, Program const* from, bool auto_clone_symbols = true);

    /// Destructor
    ~CloneContext();

    /// @copybrief ast::CloneContext::Clone
    /// @param args the arguments to forward to ast::CloneContext::Clone
    /// @return the cloned node
    template <typename... ARGS>
    auto Clone(ARGS&&... args) {
        return ctx_.Clone(std::forward<ARGS>(args)...);
    }

    /// @copybrief ast::CloneContext::CloneWithoutTransform
    /// @param args the arguments to forward to ast::CloneContext::CloneWithoutTransform
    /// @return the cloned node
    template <typename... ARGS>
    auto CloneWithoutTransform(ARGS&&... args) {
        return ctx_.CloneWithoutTransform(std::forward<ARGS>(args)...);
    }

    /// @copybrief ast::CloneContext::ReplaceAll
    /// @param args the arguments to forward to ast::CloneContext::ReplaceAll
    /// @return this CloneContext so calls can be chained
    template <typename... ARGS>
    CloneContext& ReplaceAll(ARGS&&... args) {
        ctx_.ReplaceAll(std::forward<ARGS>(args)...);
        return *this;
    }

    /// @copydoc ast::CloneContext::Replace
    template <typename WHAT, typename WITH, typename = traits::EnableIfIsType<WITH, ast::Node>>
    CloneContext& Replace(const WHAT* what, const WITH* with) {
        ctx_.Replace<WHAT, WITH>(what, with);
        return *this;
    }

    /// @copydoc ast::CloneContext::Replace
    template <typename WHAT, typename WITH, typename = std::invoke_result_t<WITH>>
    CloneContext& Replace(const WHAT* what, WITH&& with) {
        ctx_.Replace<WHAT, WITH>(what, std::forward<WITH>(with));
        return *this;
    }

    /// @copybrief ast::CloneContext::Remove
    /// @param args the arguments to forward to ast::CloneContext::Remove
    /// @return this CloneContext so calls can be chained
    template <typename... ARGS>
    CloneContext& Remove(ARGS&&... args) {
        ctx_.Remove(std::forward<ARGS>(args)...);
        return *this;
    }

    /// @copybrief ast::CloneContext::InsertFront
    /// @param args the arguments to forward to ast::CloneContext::InsertFront
    /// @return this CloneContext so calls can be chained
    template <typename... ARGS>
    CloneContext& InsertFront(ARGS&&... args) {
        ctx_.InsertFront(std::forward<ARGS>(args)...);
        return *this;
    }

    /// @copybrief ast::CloneContext::InsertBack
    /// @param args the arguments to forward to ast::CloneContext::InsertBack
    /// @return this CloneContext so calls can be chained
    template <typename... ARGS>
    CloneContext& InsertBack(ARGS&&... args) {
        ctx_.InsertBack(std::forward<ARGS>(args)...);
        return *this;
    }

    /// @copybrief ast::CloneContext::InsertBefore
    /// @param args the arguments to forward to ast::CloneContext::InsertBefore
    /// @return this CloneContext so calls can be chained
    template <typename... ARGS>
    CloneContext& InsertBefore(ARGS&&... args) {
        ctx_.InsertBefore(std::forward<ARGS>(args)...);
        return *this;
    }

    /// @copybrief ast::CloneContext::InsertAfter
    /// @param args the arguments to forward to ast::CloneContext::InsertAfter
    /// @return this CloneContext so calls can be chained
    template <typename... ARGS>
    CloneContext& InsertAfter(ARGS&&... args) {
        ctx_.InsertAfter(std::forward<ARGS>(args)...);
        return *this;
    }

    /// Clone performs the clone of the Program's AST nodes, types and symbols
    /// from #src to #dst. Semantic nodes are not cloned, as these will be rebuilt
    /// when the Builder #dst builds its Program.
    void Clone();

    /// @returns the ast::CloneContext
    inline operator ast::CloneContext&() { return ctx_; }

    /// The target Builder to clone into.
    ProgramBuilder* const dst;

    /// The source Program to clone from.
    Program const* const src;

  private:
    ast::CloneContext ctx_;
};

}  // namespace tint::program

#endif  // SRC_TINT_LANG_WGSL_PROGRAM_CLONE_CONTEXT_H_
