// Copyright 2020 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_TRANSFORM_TRANSFORM_H_
#define SRC_TRANSFORM_TRANSFORM_H_

#include <memory>
#include <string>
#include <type_traits>
#include <unordered_map>
#include <utility>

#include "src/diagnostic/diagnostic.h"
#include "src/program.h"

namespace tint {
namespace transform {

/// Data is the base class for transforms that emit extra output information
/// along with a Program.
class Data : public Castable<Data> {
 public:
  /// Constructor
  Data();

  /// Copy constructor
  Data(const Data&);

  /// Destructor
  ~Data() override;
};

/// DataMap is a map of Data unique pointers keyed by the Data's ClassID.
class DataMap {
 public:
  /// Constructor
  DataMap();

  /// Move constructor
  DataMap(DataMap&&);

  /// Constructor
  /// @param data_unique_ptrs a variadic list of additional data unique_ptrs
  /// produced by the transform
  template <typename... DATA>
  explicit DataMap(DATA... data_unique_ptrs) {
    PutAll(std::forward<DATA>(data_unique_ptrs)...);
  }

  /// Destructor
  ~DataMap();

  /// Adds the data into DataMap keyed by the ClassID of type T.
  /// @param data the data to add to the DataMap
  template <typename T>
  void Put(std::unique_ptr<T>&& data) {
    static_assert(std::is_base_of<Data, T>::value,
                  "T does not derive from Data");
    map_[&TypeInfo::Of<T>()] = std::move(data);
  }

  /// @returns a pointer to the Data placed into the DataMap with a call to
  /// Put()
  template <typename T>
  T const* Get() const {
    auto it = map_.find(&TypeInfo::Of<T>());
    if (it == map_.end()) {
      return nullptr;
    }
    return static_cast<T*>(it->second.get());
  }

  /// Add moves all the data from other into this DataMap
  /// @param other the DataMap to move into this DataMap
  void Add(DataMap&& other) {
    for (auto& it : other.map_) {
      map_.emplace(it.first, std::move(it.second));
    }
    other.map_.clear();
  }

 private:
  template <typename T0>
  void PutAll(T0&& first) {
    Put(std::forward<T0>(first));
  }

  template <typename T0, typename... Tn>
  void PutAll(T0&& first, Tn&&... remainder) {
    Put(std::forward<T0>(first));
    PutAll(std::forward<Tn>(remainder)...);
  }

  std::unordered_map<const TypeInfo*, std::unique_ptr<Data>> map_;
};

/// Interface for Program transforms
class Transform {
 public:
  /// Constructor
  Transform();
  /// Destructor
  virtual ~Transform();

  /// The return type of Run()
  class Output {
   public:
    /// Constructor
    Output();

    /// Constructor
    /// @param program the program to move into this Output
    explicit Output(Program&& program);

    /// Constructor
    /// @param program_ the program to move into this Output
    /// @param data_ a variadic list of additional data unique_ptrs produced by
    /// the transform
    template <typename... DATA>
    Output(Program&& program_, DATA... data_)
        : program(std::move(program_)), data(std::forward<DATA>(data_)...) {}

    /// The transformed program. May be empty on error.
    Program program;

    /// Extra output generated by the transforms.
    DataMap data;
  };

  /// Runs the transform on `program`, returning the transformation result.
  /// @param program the source program to transform
  /// @returns the transformation result
  virtual Output Run(const Program* program) = 0;

 protected:
  /// Clones the function `in` adding `statements` to the beginning of the
  /// cloned function body.
  /// @param ctx the clone context
  /// @param in the function to clone
  /// @param statements the statements to prepend to `in`'s body
  /// @return the cloned function
  static ast::Function* CloneWithStatementsAtStart(
      CloneContext* ctx,
      ast::Function* in,
      ast::StatementList statements);

  /// Registers a symbol renamer on `ctx` for any symbol that is found in the
  /// list of reserved identifiers.
  /// @param ctx the clone context
  /// @param names the lexicographically sorted list of reserved identifiers
  /// @param count the number of identifiers in the array `names`
  static void RenameReservedKeywords(CloneContext* ctx,
                                     const char* names[],
                                     size_t count);

  /// Registers a symbol renamer on `ctx` for any symbol that is found in the
  /// list of reserved identifiers.
  /// @param ctx the clone context
  /// @param names the lexicographically sorted list of reserved identifiers
  template <size_t N>
  static void RenameReservedKeywords(CloneContext* ctx,
                                     const char* (&names)[N]) {
    RenameReservedKeywords(ctx, names, N);
  }
};

}  // namespace transform
}  // namespace tint

#endif  // SRC_TRANSFORM_TRANSFORM_H_
