using CSUST.Data.Expr;
using JLHHJSvr.LJException;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace JLHHJSvr.LJFramework.Tools
{
    public class LJExprParser
    {
        public static bool CheckFormula(string expr,out string arg_msg)
        {
            var parser = new TExprParserChina(expr);
            // 
            arg_msg = parser.ErrorMessage;
            return parser.HasError;
        }
        public static TExprParserEx Parse(string expr)
        {
            if (string.IsNullOrEmpty(expr)) return new TExprParserChina("");
            var treatedExpr = expr;
            treatedExpr = treatedExpr.Replace("不包含", " not like ");
            treatedExpr = treatedExpr.Replace("包含", " like ");
            treatedExpr = treatedExpr.Replace("不等于", " != ");
            treatedExpr = treatedExpr.Replace("等于", " == ");
            treatedExpr = treatedExpr.Replace("大于", " > ");
            treatedExpr = treatedExpr.Replace("小于", " < ");
            treatedExpr = treatedExpr.Replace("<>", " != ");
            treatedExpr = treatedExpr.Replace("'%", "'");
            treatedExpr = treatedExpr.Replace("%'", "'");
            //treatedExpr = treatedExpr.Replace(" and ", " && ");
            //treatedExpr = treatedExpr.Replace(" or ", " || ");
            //treatedExpr = treatedExpr.Replace(" = ", " == ");
            treatedExpr = Regex.Replace(treatedExpr, "([ ]|[\\w])([=])([^=])", "$1==$3");
            treatedExpr = Regex.Replace(treatedExpr, "if(\\s*)[(]", "iif(");
            treatedExpr = Regex.Replace(treatedExpr, "int(\\s*)[(]", "floor(");
            treatedExpr = ConvertNotLikeExpression(treatedExpr);
            treatedExpr = ConvertLikeExpression(treatedExpr);
            treatedExpr = ConvertPosExpression(treatedExpr);
            treatedExpr = ConvertInExpression(treatedExpr);
            var rslt = new TExprParserChina(treatedExpr);
            if (rslt.HasError)
            {
                throw new LJCommonException($"解析表达式{expr}失败:" + rslt.ErrorMessage);
            }
            return rslt;
        }
        public static string ConvertInExpression(string expression)
        {
            string pattern = "";
            string replacement = "";
            string convertedExpression = expression;
            // 字符串in，单引号用占位符代替，数组转为字符串对比，移除所有空格
            pattern = @"('[^']*')\s+not\s+in\s+\(([^)]*)\)";
            convertedExpression = Regex.Replace(convertedExpression, pattern, match =>
            {
                var group1 = match.Groups[1].Value.Replace(" ", "").Replace("'", "quote");
                var group2 = match.Groups[2].Value.Replace(" ", "").Replace("'", "quote");
                return $"!HasStr(',{group2},',',{group1},')";
            });
            pattern = @"('[^']*')\s+in\s+\(([^)]*)\)";
            convertedExpression = Regex.Replace(convertedExpression, pattern, match =>
            {
                var group1 = match.Groups[1].Value.Replace(" ", "").Replace("'", "quote");
                var group2 = match.Groups[2].Value.Replace(" ", "").Replace("'", "quote");
                return $"HasStr(',{group2},',',{group1},')";
            });

            // 数字in，数组转为字符串对比，移除所有空格
            pattern = @"(\d*)\s+not\s+in\s+\(([^)]*)\)";
            convertedExpression = Regex.Replace(convertedExpression, pattern, match =>
            {
                var group1 = match.Groups[1].Value.Replace(" ", "");
                var group2 = match.Groups[2].Value.Replace(" ", "");
                return $"!HasStr(',{group2},',',{group1},')";
            });
            pattern = @"(\d*)\s+in\s+\(([^)]*)\)";
            convertedExpression = Regex.Replace(convertedExpression, pattern, match =>
            {
                var group1 = match.Groups[1].Value.Replace(" ", "");
                var group2 = match.Groups[2].Value.Replace(" ", "");
                return $"HasStr(',{group2},',',{group1},')";
            });

            return convertedExpression;
        }
        public static string ConvertNotLikeExpression(string expression)
        {
            string pattern = @"'([^']*)'\s+not\s+like\s+'([^']*)'";
            string replacement = "!HasStr('$1', '$2')";

            string convertedExpression = Regex.Replace(expression, pattern, replacement);

            return convertedExpression;
        }
        public static string ConvertLikeExpression(string expression)
        {
            string pattern = @"'([^']*)'\s+like\s+'([^']*)'";
            string replacement = "HasStr('$1', '$2')";

            string convertedExpression = Regex.Replace(expression, pattern, replacement);

            return convertedExpression;
        }
        public static string ConvertPosExpression(string expression)
        {
            var reg = new Regex(@"pos[(](\s*)'([^']*)'(\s*),(\s*)'([^']*)'(\s*)[)]");
            var rslt = expression;
            while (true)
            {
                var match = reg.Match(rslt);
                if (!match.Success)
                {
                    break;
                }
                var p1 = match.Groups[2].Value;
                var p2 = match.Groups[5].Value;
                var calVal = p1.IndexOf(p2) + 1;
                rslt = rslt.Replace(match.Value, calVal.ToString());
            }
            reg = new Regex("pos[(](\\s*)'([^']*)'(\\s*),(\\s*)'([^']*)'(\\s*),(\\s*)(\\d+)(\\s*)[)]");
            while (true)
            {
                var match = reg.Match(rslt);
                if (!match.Success)
                {
                    break;
                }
                var p1 = match.Groups[2].Value;
                var p2 = match.Groups[5].Value;
                var p3 = Convert.ToInt32(match.Groups[8].Value);
                var calVal = p1.IndexOf(p2, p3 - 1) + 1;
                rslt = rslt.Replace(match.Value, calVal.ToString());
            }
            reg = new Regex("pos[(](\\s*)\"([^\"]*)\"(\\s*),(\\s*)\"([^\"]*)\"(\\s*)[)]");
            while (true)
            {
                var match = reg.Match(rslt);
                if (!match.Success)
                {
                    break;
                }
                var p1 = match.Groups[2].Value;
                var p2 = match.Groups[5].Value;
                var calVal = p1.IndexOf(p2) + 1;
                rslt = rslt.Replace(match.Value, calVal.ToString());
            }
            reg = new Regex("pos[(](\\s*)\"([^\"]*)\"(\\s*),(\\s*)\"([^\"]*)\"(\\s*),(\\s*)(\\d+)(\\s*)[)]");
            while (true)
            {
                var match = reg.Match(rslt);
                if (!match.Success)
                {
                    break;
                }
                var p1 = match.Groups[2].Value;
                var p2 = match.Groups[5].Value;
                var p3 = Convert.ToInt32(match.Groups[8].Value);
                var calVal = p1.IndexOf(p2, p3 - 1) + 1;
                rslt = rslt.Replace(match.Value, calVal.ToString());
            }
            return rslt;
        }
    }
}
