// 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_TINT_TRANSFORM_TRANSFORM_H_
#define SRC_TINT_TRANSFORM_TRANSFORM_H_

#include <memory>
#include <unordered_map>
#include <utility>

#include "src/tint/castable.h"
#include "src/tint/program.h"

namespace tint::transform {

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

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

    /// Destructor
    ~Data() override;

    /// Assignment operator
    /// @returns this Data
    Data& operator=(const Data&);
};

/// 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();

    /// Move assignment operator
    /// @param rhs the DataMap to move into this DataMap
    /// @return this DataMap
    DataMap& operator=(DataMap&& rhs);

    /// 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);
    }

    /// Creates the data of type `T` with the provided arguments and adds it into
    /// DataMap keyed by the ClassID of type T.
    /// @param args the arguments forwarded to the constructor for type T
    template <typename T, typename... ARGS>
    void Add(ARGS&&... args) {
        Put(std::make_unique<T>(std::forward<ARGS>(args)...));
    }

    /// @returns a pointer to the Data placed into the DataMap with a call to
    /// Put()
    template <typename T>
    T const* Get() const {
        return const_cast<DataMap*>(this)->Get<T>();
    }

    /// @returns a pointer to the Data placed into the DataMap with a call to
    /// Put()
    template <typename T>
    T* Get() {
        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_;
};

/// 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;
};

/// Interface for Program transforms
class Transform : public Castable<Transform> {
  public:
    /// Constructor
    Transform();
    /// Destructor
    ~Transform() override;

    /// Runs the transform on `program`, returning the transformation result.
    /// @param program the source program to transform
    /// @param data optional extra transform-specific input data
    /// @returns the transformation result
    virtual Output Run(const Program* program, const DataMap& data = {}) const;

    /// @param program the program to inspect
    /// @param data optional extra transform-specific input data
    /// @returns true if this transform should be run for the given program
    virtual bool ShouldRun(const Program* program, const DataMap& data = {}) const;

  protected:
    /// Runs the transform using the CloneContext built for transforming a
    /// program. Run() is responsible for calling Clone() on the CloneContext.
    /// @param ctx the CloneContext primed with the input program and
    /// ProgramBuilder
    /// @param inputs optional extra transform-specific input data
    /// @param outputs optional extra transform-specific output data
    virtual void Run(CloneContext& ctx, const DataMap& inputs, DataMap& outputs) const;

    /// Removes the statement `stmt` from the transformed program.
    /// RemoveStatement handles edge cases, like statements in the initializer and
    /// continuing of for-loops.
    /// @param ctx the clone context
    /// @param stmt the statement to remove when the program is cloned
    static void RemoveStatement(CloneContext& ctx, const ast::Statement* stmt);

    /// CreateASTTypeFor constructs new ast::Type nodes that reconstructs the
    /// semantic type `ty`.
    /// @param ctx the clone context
    /// @param ty the semantic type to reconstruct
    /// @returns a ast::Type that when resolved, will produce the semantic type
    /// `ty`.
    static const ast::Type* CreateASTTypeFor(CloneContext& ctx, const sem::Type* ty);
};

}  // namespace tint::transform

#endif  // SRC_TINT_TRANSFORM_TRANSFORM_H_
