package com.alibaba.druid.sql.visitor.functions;

import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;
import com.alibaba.druid.sql.ast.expr.SQLValuableExpr;
import com.alibaba.druid.sql.visitor.SQLEvalVisitor;
import java.util.List;

public class Substring implements Function {
   public static final Substring instance = new Substring();

   public Object eval(SQLEvalVisitor visitor, SQLMethodInvokeExpr x) {
      List<SQLExpr> params = x.getArguments();
      int paramSize = params.size();
      SQLExpr param0 = (SQLExpr)params.get(0);
      SQLExpr param1;
      if (paramSize == 1 && x.getFrom() != null) {
         param1 = x.getFrom();
         paramSize = 2;
      } else {
         if (paramSize != 2 && paramSize != 3) {
            return SQLEvalVisitor.EVAL_ERROR;
         }

         param1 = (SQLExpr)params.get(1);
      }

      param0.accept(visitor);
      param1.accept(visitor);
      Object param0Value = param0.getAttributes().get("eval.value");
      Object param1Value = param1.getAttributes().get("eval.value");
      if (param0Value != null && param1Value != null) {
         String str = param0Value.toString();
         int index = ((Number)param1Value).intValue();
         if (paramSize == 2 && x.getFor() == null) {
            if (index <= 0) {
               int lastIndex = str.length() + index;
               return str.substring(lastIndex);
            } else {
               return str.substring(index - 1);
            }
         } else {
            SQLExpr param2 = x.getFor();
            if (param2 == null && params.size() > 2) {
               param2 = (SQLExpr)params.get(2);
            }

            param2.accept(visitor);
            Object param2Value = param2.getAttributes().get("eval.value");
            if (param2Value == null) {
               return SQLEvalVisitor.EVAL_ERROR;
            } else {
               int len = ((Number)param2Value).intValue();
               String result;
               if (index <= 0) {
                  int lastIndex = str.length() + index;
                  result = str.substring(lastIndex);
               } else {
                  result = str.substring(index - 1);
               }

               return len > result.length() ? result : result.substring(0, len);
            }
         }
      } else {
         return SQLEvalVisitor.EVAL_ERROR;
      }
   }

   public Object eval(SQLMethodInvokeExpr x) {
      List<SQLExpr> parameters = x.getArguments();

      for(SQLExpr parameter : parameters) {
         if (!(parameter instanceof SQLValuableExpr)) {
            return null;
         }
      }

      if (parameters.size() == 3) {
         Object p0 = ((SQLValuableExpr)parameters.get(0)).getValue();
         Object p1 = ((SQLValuableExpr)parameters.get(1)).getValue();
         Object p2 = ((SQLValuableExpr)parameters.get(2)).getValue();
         if (p0 instanceof Number) {
            p0 = p0.toString();
         }

         if (p0 instanceof String && p1 instanceof Integer && p2 instanceof Integer) {
            String str = (String)p0;
            int beginIndex = (Integer)p1;
            int len = (Integer)p2;
            if (len < 0) {
               return null;
            }

            int start = beginIndex - 1;
            int end = beginIndex - 1 + len;
            if (start < 0 || start >= str.length()) {
               return null;
            }

            if (end < 0 || end >= str.length()) {
               return null;
            }

            if (beginIndex > 0 && len > 0) {
               return str.substring(start, end);
            }
         }
      } else if (parameters.size() == 2) {
         Object p0 = ((SQLValuableExpr)parameters.get(0)).getValue();
         Object p1 = ((SQLValuableExpr)parameters.get(1)).getValue();
         if (p0 instanceof String && p1 instanceof Integer) {
            String str = (String)p0;
            int beginIndex = (Integer)p1;
            if (beginIndex < 0 || beginIndex >= str.length()) {
               return null;
            }

            if (beginIndex > 0) {
               return str.substring(beginIndex - 1);
            }
         }
      }

      return SQLEvalVisitor.EVAL_ERROR;
   }
}
