package cn.axzo.msg.center.message.service.todo.queryanalyze;

import cn.axzo.msg.center.message.service.todo.queryanalyze.AnalyzeResult.FailMatch;
import com.alibaba.druid.sql.ast.SQLObject;
import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;
import com.alibaba.druid.sql.ast.expr.SQLInListExpr;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
import lombok.Getter;
import lombok.RequiredArgsConstructor;

/**
 * @author yanglin
 */
@Getter
@RequiredArgsConstructor
class AnalyzeVisitor implements SQLASTVisitor {

    private final Record record;
    private final AnalyzeResult analyzeResult = new AnalyzeResult();

    @Override
    public void endVisit(SQLBinaryOpExpr x) {
        String column = EvalValueVisitor.findColumn(x.getLeft());
        if (column == null) return;
        if (shouldCollectAsFailMatch(x)) {
            Object value = record.getValue(column, EvalTypeVisitor.getType(x));
            analyzeResult.addFailMatch(new FailMatch(x, column, value));
        }
    }

    @Override
    public void endVisit(SQLInListExpr x) {
        String column = EvalValueVisitor.findColumn(x.getExpr());
        if (column == null) return;
        if (shouldCollectAsFailMatch(x)) {
            Object value = record.getValue(column, EvalTypeVisitor.getType(x));
            analyzeResult.addFailMatch(new FailMatch(x, column, value));
        }
    }

    private boolean shouldCollectAsFailMatch(SQLObject x) {
        Object value = EvalValueVisitor.getValue(x);
        if (value instanceof Boolean && (Boolean) value)
            return false;
        SQLObject parent = x.getParent();
        return parent == null || shouldCollectAsFailMatch(parent);
    }

}