#ifndef _UHDM_AST_H_
#define _UHDM_AST_H_ 1

#include "frontends/ast/ast.h"
#include <vector>
#undef cover

#include "uhdmastshared.h"
#include <memory>
#include <uhdm/uhdm.h>

namespace systemverilog_plugin
{

class AstNodeBuilder;

class UhdmAst
{
  private:
    // Logging method for exclusive use of `uhdmast_assert` macro.
    void uhdmast_assert_log(const char *expr_str, const char *func, const char *file, int line) const;

    // Walks through one-to-many relationships from given parent
    // node through the VPI interface, visiting child nodes belonging to
    // ChildrenNodeTypes that are present in the given object.
    void visit_one_to_many(const std::vector<int> child_node_types, vpiHandle parent_handle, const std::function<void(::Yosys::AST::AstNode *)> &f);

    // Walks through one-to-one relationships from given parent
    // node through the VPI interface, visiting child nodes belonging to
    // ChildrenNodeTypes that are present in the given object.
    void visit_one_to_one(const std::vector<int> child_node_types, vpiHandle parent_handle, const std::function<void(::Yosys::AST::AstNode *)> &f);

    // Visit children of type vpiRange that belong to the given parent node.
    void visit_range(vpiHandle obj_h, const std::function<void(::Yosys::AST::AstNode *)> &f);

    // Visit the default expression assigned to a variable.
    void visit_default_expr(vpiHandle obj_h);

    // Reads location info (start/end line/column numbers, file name) from `obj_h` and sets them on `target_node`.
    void apply_location_from_current_obj(::Yosys::AST::AstNode &target_node) const;
    // Reads object name from `obj_h` and assigns it to `target_node`.
    void apply_name_from_current_obj(::Yosys::AST::AstNode &target_node, bool prefer_full_name = false) const;

    // Creates node of specified `type` with location properties read from `obj_h`.
    AstNodeBuilder make_node(::Yosys::AST::AstNodeType type) const;
    // Creates node of specified `type` with location properties and name read from `obj_h`.
    AstNodeBuilder make_named_node(::Yosys::AST::AstNodeType type, bool prefer_full_name = false) const;
    // Creates AST_IDENTIFIER node with specified `id` and location properties read from `obj_h`.
    AstNodeBuilder make_ident(std::string id) const;
    // Creates signed AST_CONSTANT node with specified `value` and location properties read from `obj_h`.
    AstNodeBuilder make_const(int32_t value, uint8_t width = 32) const;
    // Creates unsigned AST_CONSTANT node with specified `value` and location properties read from `obj_h`.
    AstNodeBuilder make_const(uint32_t value, uint8_t width = 32) const;

    // Create an AstNode of the specified type with metadata extracted from
    // the given vpiHandle.
    // OBSOLETE: use `make_node` or `make_named_node` instead.
    ::Yosys::AST::AstNode *make_ast_node(::Yosys::AST::AstNodeType type, std::vector<::Yosys::AST::AstNode *> children = {},
                                         bool prefer_full_name = false);

    // Create an identifier AstNode
    // OBSOLETE: use `make_ident` instead.
    ::Yosys::AST::AstNode *make_identifier(std::string name);

    // Makes the passed node a cell node of the specified type
    void make_cell(vpiHandle obj_h, ::Yosys::AST::AstNode *node, ::Yosys::AST::AstNode *type);

    // Moves a type node to the specified node
    void move_type_to_new_typedef(::Yosys::AST::AstNode *current_node, ::Yosys::AST::AstNode *type_node);

    // Go up the UhdmAst to find a parent node of the specified type
    ::Yosys::AST::AstNode *find_ancestor(const std::unordered_set<::Yosys::AST::AstNodeType> &types);

    // Reports that something went wrong with reading the UHDM file
    void report_error(const char *format, ...) const;

    // Processes the value connected to the specified node
    ::Yosys::AST::AstNode *process_value(vpiHandle obj_h);

    // Transforms break and continue nodes into structures accepted by the AST frontend
    void transform_breaks_continues(::Yosys::AST::AstNode *loop, ::Yosys::AST::AstNode *decl_block);

    // The parent UhdmAst
    UhdmAst *parent;

    // Data shared between all UhdmAst objects
    UhdmAstShared &shared;

    // The current VPI/UHDM handle
    vpiHandle obj_h = 0;

    // The current Yosys AST node
    ::Yosys::AST::AstNode *current_node = nullptr;

    // Indentation used for debug printing
    std::string indent;

    // Mapping of names that should be replaced to new names
    std::unordered_map<std::string, std::string> node_renames;

    // Functions that process specific types of nodes
    void process_design();
    void process_parameter();
    void process_port();
    void process_module();
    void process_struct_typespec();
    void process_union_typespec();
    void process_packed_array_typespec();
    void process_array_typespec();
    void process_typespec_member();
    void process_enum_typespec();
    void process_enum_const();
    void process_custom_var();
    void process_int_var();
    void process_real_var();
    void process_array_var();
    void process_packed_array_var();
    void process_param_assign();
    void process_cont_assign();
    void process_cont_assign_net();
    void process_cont_assign_var_init();
    void process_assignment(const UHDM::BaseClass *object);
    void process_net();
    void process_packed_array_net();
    void process_array_net(const UHDM::BaseClass *object);
    void process_package();
    void process_interface();
    void process_modport();
    void process_io_decl();
    void process_always();
    void process_event_control(const UHDM::BaseClass *object);
    void process_initial();
    void process_begin(bool is_named);
    void process_operation(const UHDM::BaseClass *object);
    void process_stream_op();
    void process_list_op();
    void process_cast_op();
    void process_inside_op();
    void process_assignment_pattern_op();
    void process_tagged_pattern();
    void process_bit_select();
    void process_part_select();
    void process_indexed_part_select();
    void process_var_select();
    void process_if_else();
    void process_for();
    void process_gen_scope_array();
    void process_gen_scope();
    void process_case();
    void process_case_item();
    void process_range(const UHDM::BaseClass *object);
    void process_return();
    void process_function();
    void process_logic_var();
    void process_sys_func_call();
    // use for task calls and function calls
    void process_tf_call(::Yosys::AST::AstNodeType type);
    void process_immediate_assert();
    void process_hier_path();
    void process_logic_typespec();
    void process_int_typespec();
    void process_shortint_typespec();
    void process_longint_typespec();
    void process_time_typespec();
    void process_bit_typespec();
    void process_string_var();
    void process_string_typespec();
    void process_repeat();
    void process_byte_var();
    void process_byte_typespec();
    void process_long_int_var();
    void process_immediate_cover();
    void process_immediate_assume();
    void process_while();
    void process_gate();
    void process_primterm();
    void process_type_parameter();
    void simplify_parameter(::Yosys::AST::AstNode *parameter, ::Yosys::AST::AstNode *module_node = nullptr);
    void process_unsupported_stmt(const UHDM::BaseClass *object, bool is_error = true);

    UhdmAst(UhdmAst *p, UhdmAstShared &s, const std::string &i) : parent(p), shared(s), indent(i)
    {
        if (parent)
            node_renames = parent->node_renames;
    }

  public:
    UhdmAst(UhdmAstShared &s, const std::string &i = "") : UhdmAst(nullptr, s, i) {}

    // Visits single VPI object and creates proper AST node
    ::Yosys::AST::AstNode *process_object(vpiHandle obj_h);

    // Visits all VPI design objects and returns created ASTs
    ::Yosys::AST::AstNode *visit_designs(const std::vector<vpiHandle> &designs);

    static const ::Yosys::IdString &partial();
    static const ::Yosys::IdString &packed_ranges();
    static const ::Yosys::IdString &unpacked_ranges();
    // set this attribute to force conversion of multirange wire to single range. It is useful to force-convert some memories.
    static const ::Yosys::IdString &force_convert();
    static const ::Yosys::IdString &is_imported();
    static const ::Yosys::IdString &is_simplified_wire();
    static const ::Yosys::IdString &low_high_bound();
    static const ::Yosys::IdString &is_elaborated_module();
};

// Utility for building AstNode trees.
//
// The object members that set AstNode properties return rvalue reference to *this (i.e. to the builder object), so they can be chained.
// The children list is set using call operator (`builder_object({child0, child1, ...})`).
// Build finalization is done through cast operator to either `AstNode*` or `std::unique_ptr<AstNode>`.
//
// Usage example:
//
// 1. Define one or more factory functions for creating base AstNode object:
//
//     const auto make_node = [](AST::AstNodeType type) {
//         auto node = std::make_unique<AST::AstNode>(type);
//         // ...initialize the node if needed...
//         return AstNodeBuilder(std::move(node));
//     };
//
// 2. Use the factories to create a tree:
//
//     // AST::AstNode *const variable_node = ...
//     // AST::AstNode *const value_node = ...
//     AST::AstNode *const assign = //
//       (make_node(AST::AST_ASSIGN_EQ))({
//         (make_node(AST::AST_IDENTIFIER).str(variable_node->str)),
//         (make_node(Yosys::AST::AST_ADD))({
//           (make_node(AST::AST_IDENTIFIER).str(value_node->str)),
//           (make_node(AST::AST_CONSTANT).value(4)),
//         }),
//       });
//
// In the real code instead of custom factories illustrated in point 1 above, you probably should use predefined methods from `UhdmAst` class.
// The syntax above puts the factory call and all its method calls (but not the function call operator with the children list) in `()`. This is done
// to make `clang-format` format the code as presented. Otherwise it is heavily wrapped and a lot less readable. `()` are technically not required
// in leafs to make them format as expected, but its nice to use them for consistency.
class AstNodeBuilder
{
    using AstNode = ::Yosys::AST::AstNode;
    using AstNodeType = ::Yosys::AST::AstNodeType;

    std::unique_ptr<AstNode> node;

  public:
    explicit AstNodeBuilder(AstNodeType node_type) : node(new AstNode(node_type)) {}
    explicit AstNodeBuilder(std::unique_ptr<AstNode> node) : node(std::move(node)) {}
    ~AstNodeBuilder() { log_assert(node == nullptr); }

    AstNodeBuilder(AstNodeBuilder &&) = default;

    AstNodeBuilder() = delete;
    AstNodeBuilder(const AstNodeBuilder &) = delete;
    AstNodeBuilder &operator=(const AstNodeBuilder &) = delete;
    AstNodeBuilder &operator=(AstNodeBuilder &&) = delete;

    // Property setters

    // Sets `AstNode::children` vector
    AstNodeBuilder &&operator()(std::vector<AstNode *> children) { return node->children = std::move(children), std::move(*this); }

    // Sets `AstNode::str` value.
    AstNodeBuilder &&str(std::string s) { return node->str = std::move(s), std::move(*this); }

    // Sets `AstNode::integer` value.
    AstNodeBuilder &&integer(uint32_t v) { return node->integer = v, std::move(*this); }

    // Sets `AstNode::is_signed` value.
    AstNodeBuilder &&is_signed(bool v) { return node->is_signed = v, std::move(*this); }

    // Sets `AstNode::is_reg` value.
    AstNodeBuilder &&is_reg(bool v) { return node->is_reg = v, std::move(*this); }

    // Sets `AstNode::range_valid`.
    AstNodeBuilder &&range_valid(bool v) { return node->range_valid = v, std::move(*this); }

    // Convenience range setters

    // Sets `AstNode::range_left`, `AstNode::range_right`, `AstNode::range_valid`.
    AstNodeBuilder &&range(bool v, int left = -1, int right = 0)
    {
        node->range_valid = v;
        node->range_left = left;
        node->range_right = right;
        return std::move(*this);
    }

    // Sets `AstNode::range_left`, `AstNode::range_right`, `AstNode::range_valid = true`.
    AstNodeBuilder &&range(int left, int right) { return range(true, left, right); }

    // Convenience value setters, mainly for constants.

    // Sets node's value.
    // Sets: `AstNode::integer`, `AstNode::is_signed`, `AstNode::bits`.
    AstNodeBuilder &&value(uint32_t v, bool is_signed, int width = 32)
    {
        log_assert(width >= 0);
        node->integer = v;
        node->is_signed = is_signed;
        // `AstNode::mkconst_int` does this too.
        for (int i = 0; i < width; i++) {
            node->bits.push_back((v & 1) ? Yosys::RTLIL::State::S1 : Yosys::RTLIL::State::S0);
            v = v >> 1;
        }
        range(width - 1, 0);
        return std::move(*this);
    }

    // Sets node's value to signed 32 bit integer.
    // Sets: `AstNode::integer`, `AstNode::is_signed`, `AstNode::bits`.
    AstNodeBuilder &&value(int32_t v) { return value(v, true); }

    // Sets node's value to unsigned 32 bit integer.
    // Sets: `AstNode::integer`, `AstNode::is_signed`, `AstNode::bits`.
    AstNodeBuilder &&value(uint32_t v) { return value(v, false); }

    // Type-cast operators used for building.

    operator AstNode *() { return node.release(); }

    operator std::unique_ptr<AstNode>() { return std::move(node); }
};

} // namespace systemverilog_plugin

#endif
