package cn.com.allcode.analyser.lib ;



import com.github.gumtreediff.io.LineReader;
import com.github.gumtreediff.tree.Tree;
import com.github.gumtreediff.tree.TreeContext;
import com.github.gumtreediff.tree.Type;
import com.github.gumtreediff.tree.TypeSet;
import com.github.javaparser.Position;
import com.github.javaparser.Range;
import com.github.javaparser.ast.Modifier;
import com.github.javaparser.ast.Node;
import com.github.javaparser.ast.expr.BooleanLiteralExpr;
import com.github.javaparser.ast.expr.LiteralStringValueExpr;
import com.github.javaparser.ast.expr.Name;
import com.github.javaparser.ast.expr.SimpleName;
import com.github.javaparser.ast.expr.StringLiteralExpr;
import com.github.javaparser.ast.type.PrimitiveType;
import com.github.javaparser.ast.visitor.TreeVisitor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.*;

/**
 * 用于将JavaParser转换为Gumtree
 * JavaParser AST → GumTree Tree 转换器
 * 核心优化：
 *  1. GumTree节点关联原JavaParser Node（元数据存储）
 *  2. 修正位置信息（支持行号+列号/字符偏移量）
 *  3. 完善异常处理、日志、扩展性
 */
public class OptimizedJavaParserToGumTreeVisitor extends TreeVisitor {
    // 日志组件（替代System.out，便于排查问题）
    private static final Logger log = LoggerFactory.getLogger(OptimizedJavaParserToGumTreeVisitor.class);

    // GumTree核心上下文（存储转换后的树结构）
    protected TreeContext context = new TreeContext();

    private Deque<Tree> nodeStack  = new ArrayDeque();

    // 用于比对差异，需精准的字符偏移量
    // LineReader 核心作用：是 JavaParser（行号 + 列号）和 GumTree（字符偏移量）之间的位置转换器，依赖预构建的行索引表实现高效转换
    private FixedLineReader reader;

    public OptimizedJavaParserToGumTreeVisitor(FixedLineReader reader) throws IOException {
        this.reader = reader;

    }

    public TreeContext getTreeContext() {
        return this.context;
    }

    @Override
    public void visitPreOrder(Node node) {
        // TODO 用于遍历整棵Node树
        if (node == null) {
            log.warn("遍历到空节点，跳过");
            return;
        }
        try {
            process(node); // 处理当前节点
            // 递归处理所有子节点（转List避免并发修改异常）
            new ArrayList<>(node.getChildNodes()).forEach(this::visitPreOrder);
        } catch (Exception e) {
            log.error("处理节点[{}]时异常", node.getClass().getSimpleName(), e);
        } finally {
            // 子节点处理完，弹出当前节点（回到父节点层级）
            if (!nodeStack.isEmpty()) {
                nodeStack.pop();
            }
        }
    }

    @Override
    public void process(Node node) {
        // TODO 处理单个JavaParser节点：提取标签 → 创建GumTree节点

        // 提取节点标签（封装为方法，便于扩展）
        String label = extractNodeLabel(node);

        // 生成GumTree节点（关联原JavaParser节点）
        pushNode(node, label);

    }


    protected  String  extractNodeLabel(Node node) {
        // TODO 提取JavaParser节点的标签
        String label = "";
        if (node instanceof Name) {
            label = ((Name)node).getIdentifier();
        } else if (node instanceof SimpleName) {
            label = ((SimpleName)node).getIdentifier();
        } else if (node instanceof StringLiteralExpr) {
            label = ((StringLiteralExpr)node).asString();
        } else if (node instanceof BooleanLiteralExpr) {
            label = Boolean.toString(((BooleanLiteralExpr)node).getValue());
        } else if (node instanceof LiteralStringValueExpr) {
            label = ((LiteralStringValueExpr)node).getValue();
        } else if (node instanceof PrimitiveType) {
            label = ((PrimitiveType)node).asString();
        } else if (node instanceof Modifier) {
            label = ((Modifier)node).getKeyword().asString();
        }else {
            label = node.getClass().getSimpleName();
        }
        return label;
    }

    protected void pushNode(Node n, String label) {
        // TODO 对每个节点处理后，放入队列中
        try {
            Position begin = ((Range)n.getRange().get()).begin;
            Position end = ((Range)n.getRange().get()).end;
            // 定位到该行该列的位置
            int startPos = this.reader.positionFor(begin.line, begin.column);
            // 定位到该行该列的位置
            int length = this.reader.positionFor(end.line, end.column) - startPos + 1;
            createTreeWithMetadata(n, label, startPos, length);
        } catch (NoSuchElementException var7) {
            throw var7;
        }
    }


    /**
     * @param label
     * @param startPosition
     * @param length
     */
    private void createTreeWithMetadata(Node javaparserNode, String label, int startPosition, int length) {
        // TODO 创建GumTree节点 + 存储原JavaParser节点到元数据
        Type type = TypeSet.type(javaparserNode.getClass().getSimpleName());
        Tree gumTree = this.context.createTree(type, label);
        // 设置位置信息
        gumTree.setPos(startPosition);
        gumTree.setLength(length);

        // 关联原JavaParser节点,封装到元数据中
        String metadataKey = "ORIGINAL_JAVAPARSER_NODE";
        gumTree.setMetadata(metadataKey, javaparserNode);

        // 关联父节点（栈空=根节点，否则挂到父节点下）
        if (this.nodeStack.isEmpty()) {
            this.context.setRoot(gumTree);
        } else {
            Tree parentTree = nodeStack.peek();
            if (parentTree != null) {
                gumTree.setParentAndUpdateChildren(parentTree);
                log.debug("节点[{}]挂到父节点[{}]下", gumTree.getType().name, parentTree.getType().name);
            }
        }

        this.nodeStack.push(gumTree);
    }

}
