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

import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.ast.statement.SQLSelect;
import com.alibaba.druid.sql.ast.statement.SQLSelectStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock;
import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;
import lombok.extern.slf4j.Slf4j;

import javax.annotation.Nullable;

/**
 * @author yanglin
 */
@Slf4j
public class SimpleAnalyzer {

    private final SQLExpr whereExpr;

    public SimpleAnalyzer(String sql) {
        SQLStatement stmt = new MySqlStatementParser(sql).parseSelect();
        this.whereExpr = findWhereExpr(stmt);
    }

    public AnalyzeResult analyze(Object value) {
        try {
            return analyzeImpl(value);
        } catch (Exception e) {
            log.warn("Analyze error", e);
            AnalyzeResult result = new AnalyzeResult();
            result.setWarn(String.format("Analyze error: %s", e.getMessage()));
            return result;
        }
    }

    private AnalyzeResult analyzeImpl(Object value) {
        AnalyzeResult result = new AnalyzeResult();
        if (this.whereExpr == null) {
            result.setWarn("Can't find where expr!");
            return result;
        }
        SQLExpr whereExpr = this.whereExpr.clone();
        Record record = new Record(value);
        whereExpr.accept(EvalTypeVisitor.INSTANCE);
        whereExpr.accept(new EvalValueVisitor(record));
        AnalyzeVisitor analyzeVisitor = new AnalyzeVisitor(record);
        whereExpr.accept(analyzeVisitor);
        return analyzeVisitor.getAnalyzeResult();
    }

    @Nullable
    private SQLExpr findWhereExpr(SQLStatement stmt) {
        if (!(stmt instanceof SQLSelectStatement)) return null;
        SQLSelect select = ((SQLSelectStatement) stmt).getSelect();
        if (select == null) return null;
        MySqlSelectQueryBlock query = (MySqlSelectQueryBlock) select.getQuery();
        if (query == null) return null;
        return query.getWhere();
    }

}