// SPDX-FileCopyrightText: 2025 Siddharth Mishra <admin@brightprogrammer.in>
// SPDX-FileCopyrightText: 2025-2026 RizinOrg <info@rizin.re>
// SPDX-FileCopyrightText: 2025-2026 Billow <billow.fun@gmail.com>
// SPDX-License-Identifier: LGPL-3.0-only

#ifndef V3_IMPL_TYPES_H
#define V3_IMPL_TYPES_H

#include "../../demangler_util.h"
#include "../demangle.h"
#include "../vec.h"

typedef enum CpDemTypeKind_t {
	CP_DEM_TYPE_KIND_UNKNOWN,
	CP_DEM_TYPE_KIND_PRIMITIVE_TY,
	CP_DEM_TYPE_KIND_MANGLED_NAME,
	CP_DEM_TYPE_KIND_ENCODING,
	CP_DEM_TYPE_KIND_NAME,
	CP_DEM_TYPE_KIND_UNSCOPED_NAME,
	CP_DEM_TYPE_KIND_NESTED_NAME,
	CP_DEM_TYPE_KIND_TEMPLATE_PARAM,
	CP_DEM_TYPE_KIND_DECLTYPE,
	CP_DEM_TYPE_KIND_UNQUALIFIED_NAME,
	CP_DEM_TYPE_KIND_CTOR_NAME,
	CP_DEM_TYPE_KIND_DTOR_NAME,
	CP_DEM_TYPE_KIND_CTOR_DTOR_NAME,
	CP_DEM_TYPE_KIND_SOURCE_NAME,
	CP_DEM_TYPE_KIND_NUMBER,
	CP_DEM_TYPE_KIND_UNNAMED_TYPE_NAME,
	CP_DEM_TYPE_KIND_OPERATOR_NAME,
	CP_DEM_TYPE_KIND_TYPE,
	CP_DEM_TYPE_KIND_BUILTIN_TYPE,
	CP_DEM_TYPE_KIND_EXPRESSION,
	CP_DEM_TYPE_KIND_FOLD_EXPRESSION,
	CP_DEM_TYPE_KIND_BRACED_EXPRESSION,
	CP_DEM_TYPE_KIND_BRACED_RANGE_EXPRESSION,
	CP_DEM_TYPE_KIND_INIT_LIST_EXPRESSION,
	CP_DEM_TYPE_KIND_PREFIX_EXPRESSION,
	CP_DEM_TYPE_KIND_BINARY_EXPRESSION,
	CP_DEM_TYPE_KIND_MEMBER_EXPRESSION,
	CP_DEM_TYPE_KIND_NEW_EXPRESSION,

	CP_DEM_TYPE_KIND_UNRESOLVED_NAME,
	CP_DEM_TYPE_KIND_FUNCTION_PARAM,
	CP_DEM_TYPE_KIND_EXPR_PRIMARY,
	CP_DEM_TYPE_KIND_INTEGER_LITERAL,
	CP_DEM_TYPE_KIND_FLOAT,
	CP_DEM_TYPE_KIND_INITIALIZER,

	CP_DEM_TYPE_KIND_BASE_UNRESOLVED_NAME,
	CP_DEM_TYPE_KIND_SIMPLE_ID,
	CP_DEM_TYPE_KIND_DESTRUCTOR_NAME,
	CP_DEM_TYPE_KIND_UNRESOLVED_TYPE,
	CP_DEM_TYPE_KIND_UNRESOLVED_QUALIFIER_LEVEL,
	CP_DEM_TYPE_KIND_QUALIFIED_TYPE,
	CP_DEM_TYPE_KIND_VENDOR_EXT_QUALIFIED_TYPE,
	CP_DEM_TYPE_KIND_QUALIFIERS,
	CP_DEM_TYPE_KIND_EXTENDED_QUALIFIER,
	CP_DEM_TYPE_KIND_FUNCTION_TYPE,
	CP_DEM_TYPE_KIND_EXCEPTION_SPEC,
	CP_DEM_TYPE_KIND_CLASS_ENUM_TYPE,
	CP_DEM_TYPE_KIND_ARRAY_TYPE,
	CP_DEM_TYPE_KIND_VECTOR_TYPE,
	CP_DEM_TYPE_KIND_POINTER_TO_MEMBER_TYPE,
	CP_DEM_TYPE_KIND_TEMPLATE_TEMPLATE_PARAM,
	CP_DEM_TYPE_KIND_DIGIT,
	CP_DEM_TYPE_KIND_TEMPLATE_ARGS,
	CP_DEM_TYPE_KIND_TEMPLATE_ARG,
	CP_DEM_TYPE_KIND_SUBSTITUTION,
	CP_DEM_TYPE_KIND_SEQ_ID,
	CP_DEM_TYPE_KIND_LOCAL_NAME,
	CP_DEM_TYPE_KIND_DISCRIMINATOR,
	CP_DEM_TYPE_KIND_VENDOR_SPECIFIC_SUFFIX,
	CP_DEM_TYPE_KIND_SPECIAL_NAME,
	CP_DEM_TYPE_KIND_CALL_OFFSET,
	CP_DEM_TYPE_KIND_NV_OFFSET,
	CP_DEM_TYPE_KIND_V_OFFSET,
	CP_DEM_TYPE_KIND_BARE_FUNCTION_TYPE,
	CP_DEM_TYPE_KIND_UNSCOPED_TEMPLATE_NAME,
	CP_DEM_TYPE_KIND_TOP_LEVEL_CV_QUALIFIERS,
	CP_DEM_TYPE_KIND_NON_NEGATIVE_NUMBER,
	CP_DEM_TYPE_KIND_VALUE_NUMBER,
	CP_DEM_TYPE_KIND_VALUE_FLOAT,
	CP_DEM_TYPE_KIND_STRING_TYPE,
	CP_DEM_TYPE_KIND_POINTER_TYPE,
	CP_DEM_TYPE_KIND_REAL_PART_FLOAT,
	CP_DEM_TYPE_KIND_IMAG_PART_FLOAT,
	CP_DEM_TYPE_KIND_FIELD_SOURCE_NAME,
	CP_DEM_TYPE_KIND_INDEX_EXPRESSION,
	CP_DEM_TYPE_KIND_RANGE_BEGIN_EXPRESSION,
	CP_DEM_TYPE_KIND_RANGE_END_EXPRESSION,
	CP_DEM_TYPE_KIND_INSTANTIATION_DEPENDENT_EXPRESSION,
	CP_DEM_TYPE_KIND_ELEMENT_TYPE,
	CP_DEM_TYPE_KIND_INSTANTIATION_DEPENDENT_ARRAY_BOUND_EXPRESSION,
	CP_DEM_TYPE_KIND_ARRAY_BOUND_NUMBER,
	CP_DEM_TYPE_KIND_CLASS_TYPE,
	CP_DEM_TYPE_KIND_FUNCTION_ENCODING,
	CP_DEM_TYPE_KIND_ENTITY_NAME,
	CP_DEM_TYPE_KIND_BASE_ENCODING,
	CP_DEM_TYPE_KIND_OFFSET_NUMBER,
	CP_DEM_TYPE_KIND_VIRTUAL_OFFSET_NUMBER,
	CP_DEM_TYPE_KIND_FUNCTION_NAME,
	CP_DEM_TYPE_KIND_DATA_NAME,
	CP_DEM_TYPE_KIND_SIGNATURE_TYPE,
	CP_DEM_TYPE_KIND_NV_DIGIT,
	CP_DEM_TYPE_KIND_TEMPLATE_PARAM_DECL,
	CP_DEM_TYPE_KIND_TEMPLATE_PARAM_PACK_DECL,
	CP_DEM_TYPE_KIND_TYPE_TEMPLATE_PARAM_DECL,
	CP_DEM_TYPE_KIND_CONSTRAINED_TYPE_TEMPLATE_PARAM_DECL,
	CP_DEM_TYPE_KIND_NON_TYPE_TEMPLATE_PARAM_DECL,
	CP_DEM_TYPE_KIND_PARAMETER_PACK,
	CP_DEM_TYPE_KIND_TEMPLATE_ARGUMENT_PACK,
	CP_DEM_TYPE_KIND_PARAMETER_PACK_EXPANSION,
	CP_DEM_TYPE_KIND_NON_NEG_NUMBER,
	CP_DEM_TYPE_KIND_FWD_TEMPLATE_REF,
	CP_DEM_TYPE_KIND_MANY,
	CP_DEM_TYPE_KIND_MODULE_NAME,
	CP_DEM_TYPE_KIND_NAME_WITH_TEMPLATE_ARGS,
	CP_DEM_TYPE_KIND_CLOSURE_TY_NAME,
	CP_DEM_TYPE_KIND_CONV_OP_TY,
	CP_DEM_TYPE_KIND_ABI_TAG_TY,
	CP_DEM_TYPE_KIND_SPECIAL_SUBSTITUTION,
	CP_DEM_TYPE_KIND_EXPANDED_SPECIAL_SUBSTITUTION,
	CP_DEM_TYPE_KIND_NOEXCEPT_SPEC,
	CP_DEM_TYPE_KIND_DYNAMIC_EXCEPTION_SPEC,
	CP_DEM_TYPE_KIND_SYNTHETIC_TEMPLATE_PARAM_NAME,
	CP_DEM_TYPE_KIND_CONSTRAINED_PLACEHOLDER,
} CpDemTypeKind;

typedef struct {
	const char *buf;
	size_t len;
} DemStringView;

static inline bool dem_string_append_sv(DemString *dst, const DemStringView src) {
	if (!dst || !src.buf) {
		return false;
	}
	return dem_string_append_n(dst, src.buf, src.len);
}

static inline bool sv_form_cstr(DemStringView *dst, const char *src) {
	if (!dst || !src) {
		return false;
	}
	dst->buf = src;
	dst->len = strlen(src);
	return true;
}

static inline bool sv_eq_cstr(const DemStringView *dst, const char *src) {
	if (!dst || !src) {
		return false;
	}
	return dst->len == strlen(src) && strncmp(dst->buf, src, dst->len) == 0;
}

struct Vec_t(DemNode);

enum {
	SUB_TAG_INVALID,
	POINTER_TYPE,
	REFERENCE_TYPE,
	RVALUE_REFERENCE_TYPE,
	QUALIFIED_TYPE,
	ARRAY_TYPE,
	SPECIAL_SUBSTITUTION_ALLOCATOR,
	SPECIAL_SUBSTITUTION_BASIC_STRING,
	SPECIAL_SUBSTITUTION_STRING,
	SPECIAL_SUBSTITUTION_ISTREAM,
	SPECIAL_SUBSTITUTION_OSTREAM,
	SPECIAL_SUBSTITUTION_IOSTREAM,
};

struct DemNode_t;

// Forward template reference: stores a reference to T_ that needs resolution later
typedef struct ForwardTemplateRef {
	ut64 level; // Template parameter level
	ut64 index; // Template parameter index
	const struct DemNode_t *ref;
} ForwardTemplateRef;

typedef ForwardTemplateRef *PForwardTemplateRef;

typedef struct DemNode_t *PDemNode;

typedef struct {
	DemString name;
} PrimitiveTy;

typedef struct {
	const char *sep; // Separator string (e.g., ", " for parameters)
} ManyTy;

typedef struct {
	bool is_const : 1;
	bool is_volatile : 1;
	bool is_restrict : 1;
} CvQualifiers;

typedef struct {
	bool is_l_value : 1;
	bool is_r_value : 1;
} RefQualifiers;

static inline void free_dummy(void *ref) {
	// No-op since NodeRef is a pointer to a node owned by the context's node pool
}

typedef const struct DemNode_t *NodeRef;
VecIMPL(NodeRef, free_dummy);
static inline void VecNodeRef_free_inner(void *ptr) {
	if (ptr) {
		VecNodeRef *v = (VecNodeRef *)ptr;
		if (v->data) {
			free(v->data);
			v->data = NULL;
			v->length = 0;
			v->capacity = 0;
		}
	}
}
VecIMPL(VecNodeRef, VecNodeRef_free_inner);



typedef struct {
	NodeRef params; // Points to a node with tag=many containing parameter nodes
	NodeRef ret;
	NodeRef name;
	NodeRef requires_node;
	NodeRef exception_spec;
	NodeRef enable_if_attrs; // Ua9enable_if vendor attribute: [enable_if:cond1, cond2]
	CvQualifiers cv_qualifiers;
	RefQualifiers ref_qualifiers;
	bool has_explicit_object_param; // C++23 deducing this: first param printed with "this " prefix
} FunctionTy;

typedef struct {
	NodeRef inner_type; // The type being qualified (e.g., "QString")
	CvQualifiers qualifiers; // The CV qualifiers (const, volatile, restrict)
} QualifiedTy;

typedef struct {
	NodeRef inner_type; // The type being qualified (e.g., "QString")
	DemStringView vendor_ext;
	NodeRef template_args; // Template arguments node
} VendorExtQualifiedTy;

typedef struct {
	bool IsPartition;
	NodeRef name;
	NodeRef pare;
} ModuleNameTy;

typedef struct {
	NodeRef name;
	NodeRef template_args;
} NameWithTemplateArgs;

typedef struct {
	NodeRef template_params;
	NodeRef requires1, requires2;
	NodeRef params;
	DemStringView count;
} ClosureTyName;

typedef struct {
	NodeRef qual;
	NodeRef name;
} NestedName;

typedef struct {
	NodeRef encoding;
	NodeRef entry;
} LocalName;

typedef struct {
	NodeRef name;
	bool is_dtor;
} CtorDtorName;

typedef struct {
	NodeRef ty;
} ConvOpTy;

typedef struct {
	NodeRef ty;
	DemStringView tag;
} AbiTagTy;

typedef struct {
	NodeRef inner_ty;
	NodeRef dimension;
} ArrayTy;

typedef struct {
	NodeRef lhs;
	DemStringView op;
	NodeRef rhs;
} MemberExpr;

typedef struct {
	NodeRef lhs;
	DemStringView op;
	NodeRef rhs;
} BinaryExpr;

typedef struct {
	DemStringView prefix;
	NodeRef inner;
} PrefixExpr;

typedef struct {
	NodeRef pack, init;
	DemStringView op;
	bool is_left_fold;
} FoldExpr;

typedef struct {
	NodeRef elem, init;
	bool is_array;
} BracedExpr;

typedef struct {
	NodeRef first, last, init;
} BracedRangeExpr;

typedef struct {
	NodeRef ty;
	NodeRef inits; // many node
} InitListExpr;

typedef struct {
	NodeRef expr_list, ty, init_list;
	bool is_global;
	DemStringView op;
} NewExpr;

typedef struct {
	DemStringView type;
	DemStringView value;
} IntegerLiteralExpr;

typedef enum {
	TEMPLATEPARAMKIND_TYPE,
	TEMPLATEPARAMKIND_NONTYPE,
	TEMPLATEPARAMKIND_TEMPLATE
} TemplateParamKind;

typedef struct {
	TemplateParamKind kind;
	size_t index;
} SyntheticTemplateParamName;

typedef struct {
	NodeRef name, ty;
} NonTypeTemplateParamDecl;

typedef struct {
	NodeRef name, ty;
} TypeTemplateParamDecl;

typedef struct {
	NodeRef name, constraint;
} ConstrainedTypeTemplateParamDecl;

typedef struct {
	NodeRef name, params, requires_node;
} TemplateParamDecl;

typedef enum {
	PRIMARY,
	PPOSTFIX,
	UNARY,
	CAST,
	PTRMEM,
	MULTIPLICATIVE,
	ADDITIVE,
	SHIFT,
	SPACESHIP,
	RELATIONAL,
	EQUALITY,
	AND,
	XOR,
	IOR,
	ANDIF,
	ORIF,
	PCONDITIONAL,
	ASSIGN,
	COMMA,
	DEFAULT,
} Prec;

typedef struct DemNode_t {
	DemStringView val;
	CpDemTypeKind tag;
	Prec prec;
	ut32 subtag;
	struct Vec_t(NodeRef) children;

	union {
		struct {
			NodeRef child;
		};

		const ForwardTemplateRef *fwd_template_ref;
		PrimitiveTy primitive_ty;
		QualifiedTy qualified_ty;
		VendorExtQualifiedTy vendor_ext_qualified_ty;
		FunctionTy fn_ty;
		ManyTy many_ty;
		ModuleNameTy module_name_ty;
		NameWithTemplateArgs name_with_template_args;
		ClosureTyName closure_ty_name;
		NestedName nested_name;
		LocalName local_name;
		CtorDtorName ctor_dtor_name;
		ConvOpTy conv_op_ty;
		AbiTagTy abi_tag_ty;
		ArrayTy array_ty;
		MemberExpr member_expr;
		FoldExpr fold_expr;
		BracedExpr braced_expr;
		BracedRangeExpr braced_range_expr;
		InitListExpr init_list_expr;
		BinaryExpr binary_expr;
		PrefixExpr prefix_expr;
		NewExpr new_expr;
		IntegerLiteralExpr integer_literal_expr;
		SyntheticTemplateParamName synthetic_template_param_name;
		NonTypeTemplateParamDecl non_type_template_param_decl;
		ConstrainedTypeTemplateParamDecl constrained_type_template_param_decl;
		TemplateParamDecl template_param_decl;
	};
} DemNode;

struct DemContext_t;
typedef struct DemContext_t *PDemContext;

DemNode *DemNode_new(PDemContext ctx);
DemNode *DemNode_ctor_inplace(DemNode *asm_node, CpDemTypeKind tag, const char *val_begin, size_t val_len);
DemNode *DemNode_ctor(PDemContext ctx, CpDemTypeKind tag, const char *val_begin, size_t val_len);
void DemNode_dtor(DemNode *dan);
bool DemNode_init(DemNode *dan);
void DemNode_deinit(DemNode *dan);
bool DemNode_is_empty(DemNode *x);
void DemNode_copy(DemNode *dst, const DemNode *src);
void DemNode_move(DemNode *dst, DemNode *src);
void DemNode_init_clone(DemNode *dst, const DemNode *src);
#define DemNode_non_empty(X) (!DemNode_is_empty(X))

DemNode *make_primitive_type_inplace(DemNode *x, const char *begin, const char *end, const char *name, size_t name_len);
DemNode *make_primitive_type(PDemContext ctx, const char *begin, const char *end, const char *name, size_t name_len);
DemNode *make_name_with_template_args(PDemContext ctx, const char *begin, const char *end, DemNode *name_node, DemNode *template_args_node);

static inline void PDemNode_free(void *ptr) {
	if (ptr) {
		DemNode *node = *(DemNode **)ptr;
		if (node) {
			DemNode_dtor(node);
		}
	}
}

VecIMPL(PDemNode, PDemNode_free);

typedef VecT(PDemNode) NodeList;
void NodeList_copy(NodeList *dst, const NodeList *src);

static inline void PNodeList_free(void *self) {
}

typedef NodeList *PNodeList;
VecIMPL(PNodeList, PNodeList_free);

static inline void ForwardTemplateRef_free(void *pfwd) {
	if (pfwd && *(void **)pfwd) {
		free(*(void **)pfwd);
	}
}

VecIMPL(PForwardTemplateRef, ForwardTemplateRef_free);

/**
 * Parser context that deeply contains string iterator, metadata, and trace graph.
 * This is the main context passed to all rule functions.
 */
typedef struct DemParser {
	const char *beg;
	const char *end;
	const char *cur;

	VecT(NodeRef) detected_types;
	VecT(NodeRef) names;
	VecT(NodeRef) * outer_template_params;
	VecT(VecNodeRef) template_params;
	VecT(PForwardTemplateRef) forward_template_refs;
	VecT(NodeRef) orphan_nodes; // Nodes orphaned by nested encoding save/restore (freed at deinit)
	VecT(PForwardTemplateRef) orphan_fwd_refs; // ForwardTemplateRefs orphaned by nested encoding (freed at deinit)
	bool not_parse_template_args;
	bool permit_forward_template_refs;
	bool in_constraint_expr; // When true, unresolvable template params are printed as raw names (e.g., TL0_)
	bool trace;
	size_t parse_lambda_params_at_level;
	unsigned num_synthetic_template_parameters[3];
	size_t recursion_depth;
	size_t total_calls; // Monotonic counter: total rule invocations (never decremented)

	CpDemOptions options;
	void *context; // DemContext
} DemParser;

typedef struct {
	bool is_conversion_ctor_dtor;
	bool end_with_template_args;
	bool has_explicit_object_param; // C++23 deducing this: H after N in nested-name
	size_t fwd_template_ref_begin;
	CvQualifiers cv_qualifiers;
	RefQualifiers ref_qualifiers;
} NameState;

void NameState_init(NameState *ns, const DemParser *p);

/**
 * Error codes for parsing failures
 */
typedef enum DemErrorCode {
	DEM_ERR_OK = 0,
	DEM_ERR_UNEXPECTED_END,
	DEM_ERR_OUT_OF_MEMORY,
	DEM_ERR_INVALID_SYNTAX,
	DEM_ERR_UNKNOWN
} DemErrorCode;

/**
 * Result of a parsing rule.
 * Contains either the output node (on success) or error code (on failure).
 */
typedef struct DemResult {
	DemNode *output; /**< Output node (allocated on success) */
	DemErrorCode error; /**< Error code (on failure) */
} DemResult;

VecIMPL(DemNode, DemNode_deinit);

typedef struct DemContext_t {
	VecPDemNode node_pool;
	DemParser parser;
	DemResult result;
	DemString output;
} DemContext;

void DemContext_init(DemContext *ctx);
void DemContext_deinit(DemContext *ctx);

/**
 * Type of rules.
 * @param p Parser context
 * @param r Result structure to fill
 * @return true on success (r->output set), false on failure (r->error may be set)
 */
typedef bool (*DemRule)(DemParser *p, DemResult *r);

// DemParser helper functions
void DemParser_init(DemParser *p, CpDemOptions options, const char *input);
void DemParser_deinit(DemParser *p);
void DemResult_deinit(DemResult *r);
bool parse_rule(DemContext *ctx, const char *mangled, DemRule rule, CpDemOptions opts);

// Helper functions
bool append_type(DemParser *p, const DemNode *x);
NodeRef substitute_get(DemParser *p, ut64 id);
NodeRef template_param_get(DemParser *p, ut64 level, ut64 index);
bool resolve_forward_template_refs(DemParser *p, NodeRef node);

#endif // V3_IMPL_TYPES_H
