import Delegate from './Delegate'
import ExpressionType from '../enums/ExpressionType'
import BreakWayException from '../exception/BreakWayException'
import ContinueWayException from '../exception/ContinueWayException'
import ServiceException from '../exception/ServiceException'
import ReturnWayException from '../exception/ReturnWayException'
import ExpressionException from '../exception/ExpressionException'
import Vue from 'vue'

export default class Expression {
  /**
   * 节点类型
   */
  type
  /**
   * 节点值
   */
  value
  /**
   * 节点对应位置
   */
  pos
  /**
   * 子节点
   */
  children
  /**
   * 运行时对应的Delegate，Delegate中保存有实参
   */
  delegate
  constructor (type, pos, value, children, expression) {
    this.type = type
    this.value = value
    this.pos = pos
    if (children) {
      this.children = children
    } else if (expression) {
      this.children = [expression]
    } else {
      this.children = []
    }
  }

  /**
   * 产生常数
   */
  static Constant (value, pos) {
    return new Expression(ExpressionType.Constant, pos, value)
  }

  /**
   * 产生Lambda
   */
  static Lambda (lambdaExp, pos) {
    return new Expression(ExpressionType.Lambda, pos, lambdaExp)
  }

  /**
   * 产生Return
   */
  static Return (objExp, pos) {
    return new Expression(ExpressionType.Return, pos, null, undefined, objExp)
  }

  /**
   * 产生Break
   */
  static Break (pos, objExp) {
    return new Expression(ExpressionType.Break, pos, null, undefined, objExp)
  }

  /**
   * 产生Continue
   */
  static Continue (pos, objExp) {
    return new Expression(ExpressionType.Continue, pos, null, undefined, objExp)
  }

  /**
   * 产生Throw
   */
  static Throw (objExp, pos) {
    return new Expression(ExpressionType.Throw, pos, null, undefined, objExp)
  }

  /**
   * 产生Assert
   */
  static Assert (objExp, pos) {
    return new Expression(ExpressionType.Assert, pos, null, undefined, objExp)
  }

  /**
   * 产生Validate
   */
  static Validate (objExp, pos) {
    return new Expression(ExpressionType.Validate, pos, null, undefined, objExp)
  }

  /**
   * 产生标识符
   */
  static Identity (value, pos) {
    return new Expression(ExpressionType.Identity, pos, value)
  }

  /**
   * 产生Json对象，value=null, children=属性值对
   */
  static Json (attrs, pos) {
    const result = new Expression(ExpressionType.Json, pos)
    result.children.push(...attrs)
    return result
  }

  /**
   * 逗号表达式, value=null, children=各表达式
   */
   static Comma (children, pos) {
    const result = new Expression(ExpressionType.Comma, pos)
    result.children.push(...children)
    return result
  }

  /**
   * 函数调用
   */
  static Call (objExp, name, params, pos) {
    const result = new Expression(ExpressionType.Call, pos, name)
    result.children.push(objExp)
    // 把所有参数加入函数调用子中
    result.children.push(...params)
    return result
  }

  /**
   * 产生JSON数组
   */
  static Array (params, pos) {
    return new Expression(ExpressionType.Array, pos, null, params)
  }

  /**
   * 产生参数
   */
  static Param (objExp, value, pos) {
    const result = new Expression(ExpressionType.Param, pos, value)
    result.children.push(objExp)
    return result
  }

  /**
   * 产生对象属性
   */
  static Property (objExp, name, pos) {
    const result = new Expression(ExpressionType.Property, pos, name)
    result.children.push(objExp)
    return result
  }

  /**
   * 产生属性表达式，value=属性名，children[0]=属性值
   */
  static Attr (name, value, pos) {
    const result = new Expression(ExpressionType.Attr, pos, name)
    result.children.push(value)
    return result
  }

  /**
   * 产生赋值语句，value=属性名/变量名，child[0]=赋值对象，child[1]=赋值内容
   */
  static Assign (objExp, exp, name, pos) {
    const result = new Expression(ExpressionType.Assign, pos, name)
    result.children.push(objExp)
    result.children.push(exp)
    return result
  }

  /**
   * 产生异常
   */
  static Try (tryExp, catches, pos, finallyExp) {
    const tryFinally = []
    tryFinally.push(tryExp)
    if (finallyExp) {
      tryFinally.push(finallyExp)
    }

    const result = new Expression(ExpressionType.Try, pos, tryFinally)
    result.children.push(...catches)
    return result
  }

  /**
   * 产生Catch
   */
  static Catch (className, varName, catches, pos) {
    const catchParameter = []
    catchParameter.push(className)
    catchParameter.push(varName)

    const result = new Expression(ExpressionType.Catch, pos, catchParameter)
    result.children.push(catches)
    return result
  }

  /**
   * 产生一个条件语句, test:条件，ifTrue:为真时结果，ifFalse:为假时结果
   */
  static Condition (test, ifTrue, ifFalse, source, pos) {
    const result = new Expression(ExpressionType.Condition, pos, source)
    result.children.push(test)
    result.children.push(ifTrue)
    result.children.push(ifFalse)
    return result
  }

  /**
   * 产生逻辑非语句
   */
  static Not (exp, source, pos) {
    const result = new Expression(ExpressionType.Not, pos, source)
    result.children.push(exp)
    return result
  }

  /**
   * 产生逻辑与语句
   */
  static And (left, right, source, pos) {
    const result = new Expression(ExpressionType.And, pos, source)
    result.children.push(left)
    result.children.push(right)
    return result
  }

  /**
   * 产生逻辑或语句
   */
  static Or (left, right, source, pos) {
    const result = new Expression(ExpressionType.Or, pos, source)
    result.children.push(left)
    result.children.push(right)
    return result
  }

  /**
   * 产生>比较运算
   */
  static GreaterThan (left, right, source, pos) {
    const result = new Expression(ExpressionType.GreaterThan, pos, source)
    result.children.push(left)
    result.children.push(right)
    return result
  }

  /**
   * 产生>=比较运算
   */
  static GreaterThanOrEqual (left, right, source, pos) {
    const result = new Expression(ExpressionType.GreaterThanOrEqual, pos, source)
    result.children.push(left)
    result.children.push(right)
    return result
  }

  /**
   * 产生<比较运算
   */
  static LessThan (left, right, source, pos) {
    const result = new Expression(ExpressionType.LessThan, pos, source)
    result.children.push(left)
    result.children.push(right)
    return result
  }

  /**
   * 产生<=比较运算
   */
  static LessThanOrEqual (left, right, source, pos) {
    const result = new Expression(ExpressionType.LessThanOrEqual, pos, source)
    result.children.push(left)
    result.children.push(right)
    return result
  }

  /**
   * 产生==比较运算
   */
  static Equal (left, right, source, pos) {
    const result = new Expression(ExpressionType.Equal, pos, source)
    result.children.push(left)
    result.children.push(right)
    return result
  }

  /**
   * 产生!=比较运算
   */
  static NotEqual (left, right, source, pos) {
    const result = new Expression(ExpressionType.NotEqual, pos, source)
    result.children.push(left)
    result.children.push(right)
    return result
  }

  /**
   * 产生+运算
   */
  static Add (left, right, source, pos) {
    const result = new Expression(ExpressionType.Add, pos, source)
    result.children.push(left)
    result.children.push(right)
    return result
  }

  /**
   * 产生-运算
   */
  static Subtract (left, right, source, pos) {
    const result = new Expression(ExpressionType.Subtract, pos, source)
    result.children.push(left)
    result.children.push(right)
    return result
  }

  /**
   * 产生*运算
   */
  static Multiply (left, right, source, pos) {
    const result = new Expression(ExpressionType.Multiply, pos, source)
    result.children.push(left)
    result.children.push(right)
    return result
  }

  /**
   * 产生/运算
   */
  static Divide (left, right, source, pos) {
    const result = new Expression(ExpressionType.Divide, pos, source)
    result.children.push(left)
    result.children.push(right)
    return result
  }

  /**
   * 产生%运算
   */
  static Modulo (left, right, source, pos) {
    const result = new Expression(ExpressionType.Modulo, pos, source)
    result.children.push(left)
    result.children.push(right)
    return result
  }

  /**
   * 产生字符串连接运算
   */
  static Concat (left, right, source, pos) {
    const result = new Expression(ExpressionType.Concat, pos, source)
    result.children.push(left)
    result.children.push(right)
    return result
  }

  /**
   * 产生数组下标
   */
  static ArrayIndex (objExp, indexExp, source, pos) {
    const result = new Expression(ExpressionType.ArrayIndex, pos, source)
    result.children.push(objExp)
    result.children.push(indexExp)
    return result
  }

  /**
   * 产生for循环
   */
  static For (objExp, forExp, source, pos) {
    const result = new Expression(ExpressionType.For, pos, source)
    result.children.push(objExp)
    result.children.push(forExp)
    return result
  }

  static isNumberC (str) {
    return !isNaN(Number(str))
  }

  /**
   * 覆盖toString方法，显示树状的节点信息，方便调试
   */
  toString (level) {
    if (!level) {
      return this.toString(0)
    } else {
      // 显示自己的类型及名称
      let result = this.space(level) + 'type: ' + this.type + ', value: ' +
        (this.value ? this.value.toString() : 'null') + '[\n]'
      // 递归显示子
      for (let i = 0; i < this.children.length; i++) {
        const child = this.children[i]
        result += (child ? child.toString(level + 1) : this.space(level + 1) + 'null\n')
      }
      result += this.space(level) + ']\n'
      return result
    }
  }

  /**
   * 执行条件处理
   */
  async condition () {
    // 条件
    const condExp = this.children[0]
    // 为真时表达式
    const isTrue = this.children[1]
    // 为假时表达式
    const isFalse = this.children[2]
    // 如果条件返回的不是bool值，则非空值为真，空值为假
    const obj = await condExp?.invoke()
    const cond = this.getBoolean(obj)
    // 为真，返回为真的表达式，否则，返回为假的表达式
    return cond ? await isTrue?.invoke() : await isFalse?.invoke()
  }

  /**
   * 执行for循环
   */
  async loop () {
    const objExp = this.children[0]
    // 获取对象，for循环
    const obj = await objExp?.invoke()

    if (obj instanceof Array) {
      // 获取循环体，循环体中row代表每一项对象, 把对象传递给循环体执行
      const body = this.children[1]
      const array = obj
      for (let i = 0; i < array.length; i++) {
        this.delegate?.put('rowIndex', i)
        this.delegate?.put('row', array[i])
        try {
          await body?.invoke()
        } catch (e) {
          if (e instanceof BreakWayException) {
            break
          } else if (e instanceof ContinueWayException) {
            // ignore
          } else {
            throw e
          }
        }
      }
    } else if (obj instanceof Object) {
      // 获取循环体，循环体中row代表每一项对象, 把对象传递给循环体执行
      const body = this.children[1]
      for (const key in obj) {
        this.delegate?.put('rowKey', key)
        this.delegate?.put('row', obj[key])
        try {
          await body?.invoke()
        } catch (e) {
          if (e instanceof BreakWayException) {
            break
          } else if (e instanceof ContinueWayException) {
            // ignore
          } else {
            throw e
          }
        }
      }
    } else {
      let start = 0
      let length
      try {
        if (objExp?.children.length === 2) {
          start = await objExp?.children[0]?.invoke()
          length = await objExp?.children[1]?.invoke()
        } else if (typeof obj === 'number') {
          length = obj
        } else {
          throw new ServiceException('for循环只接收集合对象，整数或两个整数的组合')
        }
      } catch (e) {
        throw new ServiceException('for循环只接收集合对象，整数或两个整数的组合')
      }
      // 获取循环体，循环体中row代表索引
      for (let i = start; i < length; i++) {
        const body = this.children[1]
        this.delegate?.put('row', i)
        try {
          await body?.invoke()
        } catch (e) {
          if (e instanceof BreakWayException) {
            break
          } else if (e instanceof ContinueWayException) {
            // ignore
          } else {
            throw e
          }
        }
      }
    }
    return obj
  }

  /**
   * 执行集合的where过滤
   */
  async where () {
    const result = []

    const objExp = this.children[0]
    // 获取对象，where循环只针对JSONArray及list
    let array

    const ret = await objExp?.invoke()
    if (Array.isArray(ret)) {
      array = ret
    } else {
      throw new ServiceException('where循环只针对Array')
    }

    // 获取过滤内容，其中row代表每一项对象, 把对象传递进去执行
    const body = this.children[1]
    for (let i = 0; i < array.length; i++) {
      const value = array[i]
      this.delegate?.put('row', value)
      const value2 = await body?.invoke()
      if (value2 === true) {
        result.push(value) // 添加符合条件的元素
      }
    }
    return result
  }

  /**
   * 执行集合的sum求和，求和结果为BigDecimal
   */
  async sum () {
    let result = 0
    const objExp = this.children[0]
    // 获取对象，sum循环只针对JSONArray
    const array = await objExp?.invoke()
    // 获取过滤内容，其中row代表每一项对象, 把对象传递进去执行
    const body = this.children[1]
    for (let i = 0; i < array.length(); i++) {
      const value = array.get(i)
      this.delegate?.put('row', value)
      const decimal = await body?.invoke().toString()
      if (decimal) {
        result = result + Number(decimal)
      }
    }
    return result
  }

  /**
   * 对函数或者取属性结果进行数值转换
   */
  convert (source) {
    if (typeof source === 'number') {
      return Number(source)
    } else {
      return source
    }
  }

  /**
   * 返回Json对象的结果，返回一个Json对象
   */
  async json () {
    const result = {}
    for (const child of this.children) {
      const name = child?.value.toString()
      const value = await child?.children[0]?.invoke()
      result[name] = value
    }
    return result
  }

  /**
   * 返回JSONArray结果
   */
  async array () {
    const result = []
    for (const child of this.children) {
      // 调用处理结果
      const value = await child?.invoke()
      result.push(value)
    }
    return result
  }

  /**
   * 根据值返回boolean结果
   */
  getBoolean (obj) {
    // 如果条件返回的不是bool值，则非空值为真，空值为假
    let cond
    if (typeof obj === 'boolean') {
      cond = Boolean(obj)
    } else {
      cond = (obj != null)
    }
    return cond
  }

  /**
   * 执行赋值过程
   */
  async assign () {
    // 属性值
    const right = this.children[1]
    const value = await right?.invoke()
    // 获取属性
    const name = this.value
    if (this.delegate?.getLambdaOutProps().includes(name)) {
      throw new ServiceException('lambda 表达式中使用的外层参数[' + name + ']为常量，不允许显性改变')
    }
    // 要赋值的对象，空代表给变量赋值
    const left = this.children[0]
    if (left == null) {
      this.delegate?.put(name, value)
    } else {
      const obj = await left.invoke()
      try {
        obj[name] = value
        return value
      } catch (e) {
        throw new ServiceException('属性赋值错误：' + name)
      }
    }
    return value
  }

  /**
   * 获取对象属性
   */
  async property (key = this.value.toString()) {
    const objExp = this.children[0]
    // 获取对象
    const obj = await objExp?.invoke()
    // 属性名
    return this.convert(obj[key])
  }

  /**
   * 获取数组元素
   */
  async arrayIndex () {
    const objExp = this.children[0]
    const indexExp = this.children[1]
    // 获取对象
    const obj = await objExp?.invoke()
    // 如果对象为JSONArray，调用JSONArray的方法
    if (obj instanceof Array) {
      const list = obj
      // 获取下标值
      const index = Number(await indexExp?.invoke())
      const oRet = list[index]
      return this.convert(oRet)
    } else {
      try {
        // 获取键
        const key = (await indexExp?.invoke()).toString()
        return await this.property(key)
      } catch (e) {
        if (!(e instanceof Error)) {
          // eslint-disable-next-line no-ex-assign
          e = new Error(e)
        }
        throw new ExpressionException(this.delegate?.getSource(), this.pos, e)
      }
    }
  }

  /**
   * 产生多个空格
   */
  space (n) {
    let result = ''
    for (let i = 0; i < n; i++) {
      result += ' '
    }
    return result
  }

  /**
   * 跳出业务
   */
  async returnBusiness () {
    const value = await this.children[0]?.invoke()
    throw new ReturnWayException(value)
  }

  /**
   * 抛出业务异常
   */
  async throwException () {
    let result = await this.children[0]?.invoke()
    if (typeof result === 'object') {
      throw new ServiceException(result.msg, result.status)
    } else if (result instanceof Error) {
      const e = result
      if (e instanceof ServiceException) {
        throw e
      }
      throw new ExpressionException(this.delegate?.getSource(), this.pos, e)
    } else {
      if (result === undefined || result === '') {
        result = '未定义异常'
      }
      throw new ServiceException(result.toString(), 400)
    }
  }

  /**
   * 断言处理
   */
  async assertExp () {
    const expression = this.children[0]
    const result = await expression?.invoke()
    if (typeof result === 'boolean') {
      if (!result) {
        throw new ServiceException('断言校验失败', 400)
      }
    } else {
      throw new ServiceException('assert仅接收boolean结果')
    }
    return true
  }

  /**
   * 参数校验
   */
  async validateParams () {
    const result = await this.children[0]?.invoke()
    if (typeof result === 'object') {
      const validateJson = result
      const params = this.delegate.get('data')
      this.validateMain('data', params, validateJson)
    } else {
      throw new ServiceException('validate仅接收json格式的对象')
    }
    return result
  }

  /**
   * lambda
   */
  lambda () {
    return new Delegate(this.value, this.delegate?.getSource(), this.delegate?.getObjectNames())
  }

  /**
   * 参数校验实现
   */
  validateMain (validateItemKey, params, validateJson) {
    for (const key in validateJson) {
      const item = validateJson[key]
      const validateMode = item.mode || 'normal'
      switch (validateMode) {
        case 'normal': {
          const hasParams = Object.prototype.hasOwnProperty.call(params, key) && params[key] != null
          if (!hasParams) {
            if (item.required) {
              const message = item.message || '参数校验失败，' + validateItemKey + '>>' + key + '不能为空'
              throw new ServiceException(message, 400)
            }
            if (item.default !== undefined) {
              params[key] = item.default
            }
          }
          // items用于对JSON参数的成员进行校验
          if (item.items) {
            this.validateMain(validateItemKey + '>>' + key, params[key], item.items)
          }
          break
        }
        case 'atLeastOne': {
          const fields = item.fields
          let isValidate = false
          for (let i = 0; i < fields.length; i++) {
            const field = fields[i]
            const fieldName = field
            const hasParam = Object.prototype.hasOwnProperty.call(params, fieldName) && params[fieldName] != null
            if (hasParam) {
              isValidate = true
              break
            }
          }
          if (!isValidate) {
            throw new ServiceException(item.message || '参数校验失败:参数组' + fields + '至少有一个不能为空', 400)
          }
          break
        }
      }
    }
  }

  async Param () {
    return await this.children[0]?.invoke()
  }

  /**
   * 执行 Try-Catch-Finally 语句块
   */
  async try () {
    const exps = this.value
    const tryExp = exps[0]

    try {
      // 执行 try 块
      return await tryExp.invoke()
    } catch (ex) {
      const e = ex instanceof Error ? (ex).cause : ex

      // 执行 catch 块
      for (const exp of this.children) {
        const catchValues = exp?.value
        const typeName = catchValues[0]
        const varName = catchValues[1]

        // 找到了 catch 部分，获取异常类型
        if (this.isEqual(e, typeName)) {
          const catchExp = exp?.children
          // 把异常值变成变量
          this.delegate?.put(varName, e)
          return await catchExp[0].invoke()
        }
      }

      // 未匹配到异常，重新抛出原异常
      throw ex
    } finally {
      // 执行 finally 块
      if (exps.length > 1) {
        const finallyExp = exps[1]
        if (finallyExp != null) {
          await finallyExp.invoke()
        }
      }
    }
  }

  /**
   * 判断异常类型是否匹配
   */
  isEqual (exception, typeName) {
    if (typeName === 'Exception' || typeName === 'Error') {
      return true
    }
    return exception && exception.constructor.name === typeName
  }

  /**
   * 执行
   */
  async invoke () {
    try {
      switch (this.type) {
        // 逻辑运算
        case ExpressionType.Or: {
          const left = this.children[0]
          const l = this.getBoolean(await left.invoke())
          if (l === true) {
            return true
          } else {
            const right = this.children[1]
            return this.getBoolean(await right.invoke())
          }
        }
        case ExpressionType.And: {
          const left = this.children[0]
          const right = this.children[1]
          const l = this.getBoolean(await left.invoke())
          if (l === true) {
            return this.getBoolean(await right.invoke())
          } else {
            return false
          }
        }
        case ExpressionType.Not: {
          const left = this.children[0]
          return !this.getBoolean(await left.invoke())
        }
        // 算数运算
        case ExpressionType.Add:
        case ExpressionType.Subtract:
        case ExpressionType.Multiply:
        case ExpressionType.Divide:
        case ExpressionType.Modulo: {
          return await this.math()
        }
        // 字符串连接
        case ExpressionType.Concat: {
          const left = this.children[0]
          const right = this.children[1]
          let l = await left.invoke()
          if (l == null) {
            l = 'null'
          }
          let r = await right.invoke()
          if (r == null) {
            r = 'null'
          }
          return Expression.toJSONString(l) + Expression.toJSONString(r)
        }
        // 返回JSON
        case ExpressionType.Json: {
          return await this.json()
        }
        // 返回JSONArray
        case ExpressionType.Array: {
          return await this.array()
        }
        // 比较运算
        case ExpressionType.GreaterThan:
        case ExpressionType.GreaterThanOrEqual:
        case ExpressionType.LessThan:
        case ExpressionType.LessThanOrEqual: {
          const left = this.children[0]
          const right = this.children[1]
          const l = await left.invoke()
          const r = await right.invoke()
          if (l == null || r == null) {
            return false
          }
          // 两个字符串比较
          if (typeof l === 'string' && typeof r === 'string') {
            const result = l.localeCompare(r) // 使用localeCompare来比较字符串
            return this.compare(result)
          } else {
            const dl = Number(l) // 转换成数字
            const dr = Number(r) // 转换成数字
            if (isNaN(dl) || isNaN(dr)) {
              return false // 如果转换失败，返回 false
            }
            return this.compare(dl - dr) // 进行数字比较
          }
        }
        // 比较运算
        case ExpressionType.Equal:
        case ExpressionType.NotEqual: {
          const left = this.children[0]
          const right = this.children[1]
          let l = await left.invoke()
          let r = await right.invoke()

          // 如果 l 或 r 为 null，替换成字符串 "null"
          if (l == null) {
            l = 'null'
          }
          if (r == null) {
            r = 'null'
          }

          let equals

          // 校验参考的是 JS 的 ==，即宽松相等比较
          if ((typeof l === 'number' && typeof r === 'number') ||
            ((typeof l === 'number' || typeof r === 'number') && this.isNumberC(l.toString()) && this.isNumberC(r.toString()))) {
            // 比较两个数字，使用 Number 进行转换
            equals = Number(l) === Number(r)
          } else {
            // 比较字符串
            equals = String(l) === String(r)
          }

          return this.type === ExpressionType.Equal ? equals : !equals
        }
        // 常数
        case ExpressionType.Constant: {
          return this.value
        }
        // 标识符，获取实参对象
        case ExpressionType.Identity: {
          // 如果参数不存在，返回空
          const name = this.value
          if (!this.delegate?.containsKey(name)) {
            return null
          }
          return this.delegate?.get(name)
        }
        // 条件语句
        case ExpressionType.Condition: {
          return await this.condition()
        }
        // 获取属性值
        case ExpressionType.Property: {
          return await this.property()
        }
        // 获取数组元素
        case ExpressionType.ArrayIndex: {
          return await this.arrayIndex()
        }
        // 函数调用
        case ExpressionType.Call: {
          return await this.call()
        }
        // For循环
        case ExpressionType.For: {
          return await this.loop()
        }
        // 属性赋值
        case ExpressionType.Assign: {
          return await this.assign()
        }
        // 逗号表达式
        case ExpressionType.Comma: {
          let value = 0
          for (const child of this.children) {
            value = await child?.invoke()
          }
          return value
        }
        // 异常处理
        case ExpressionType.Try: {
          return await this.try()
        }
        // 参数
        case ExpressionType.Param: {
          return await this.Param()
        }
        // Return
        case ExpressionType.Return: {
          return await this.returnBusiness()
        }
        // Throw
        case ExpressionType.Throw: {
          return await this.throwException()
        }
        // Assert
        case ExpressionType.Assert: {
          return await this.assertExp()
        }
        // Validate
        case ExpressionType.Validate: {
          return await this.validateParams()
        }
        // Lambda
        case ExpressionType.Lambda: {
          return await this.lambda()
        }
        // Break
        case ExpressionType.Break: {
          throw new BreakWayException()
        }
        // Continue
        case ExpressionType.Continue: {
          throw new ContinueWayException()
        }
        default: {
          throw new ServiceException('无效操作')
        }
      }
    } catch (ex) {
      if (ex instanceof ReturnWayException ||
        ex instanceof BreakWayException ||
        ex instanceof ContinueWayException ||
        ex instanceof ExpressionException) {
        throw ex
      } else {
        if (!(ex instanceof Error)) {
          // eslint-disable-next-line no-ex-assign
          ex = new Error(ex)
        }
        throw new ExpressionException(this.delegate?.getSource(), this.pos, ex)
      }
    }
  }

  compare (result) {
    switch (this.type) {
      case ExpressionType.GreaterThan:
        return result > 0
      case ExpressionType.GreaterThanOrEqual:
        return result >= 0
      case ExpressionType.LessThan:
        return result < 0
      case ExpressionType.LessThanOrEqual:
        return result <= 0
      default:
        throw new ServiceException('未知类型')
    }
  }

  /**
   * 执行数学运算
   *
   * @return number
   */
  async math () {
    const left = this.children[0]
    const right = this.children[1]
    const oLeft = await left.invoke()
    const oRight = await right.invoke()

    // 统一将输入转换为浮点数，既支持整数也支持浮点数
    const l = Number(oLeft) // 使用 Number 统一转换
    const r = Number(oRight) // 使用 Number 统一转换

    if (isNaN(l) || isNaN(r)) {
      throw new ServiceException('无效的数字')
    }

    switch (this.type) {
      case ExpressionType.Add:
        return l + r
      case ExpressionType.Subtract:
        return l - r
      case ExpressionType.Multiply:
        return l * r
      case ExpressionType.Divide:
        return r !== 0 ? l / r : NaN // 防止除以0
      case ExpressionType.Modulo:
        return l % r
      default:
        throw new ServiceException('不识别的算数操作符')
    }
  }

  /**
   * 执行函数调用
   */
  async call () {
    // 函数名
    const name = this.value

    // 如果是 where 函数，调用 where 过滤
    if (name === 'where') {
      return await this.where()
    }

    // 如果是 sum 求和函数，调用 sum 求和
    if (name === 'sum') {
      return await this.sum()
    }

    const objExp = this.children[0]
    // 获取对象
    const obj = await objExp.invoke()

    if (obj == null) {
      throw new ServiceException(`对象[${objExp.value}]为null`)
    }

    if (name === 'toString') {
      return Expression.toJSONString(obj)
    }

    // 获得参数计算结果
    const params = []
    for (let i = 1; i < this.children.length; i++) {
      const paramExp = this.children[i]
      params.push(await paramExp.invoke())
    }

    if (name === 'runExpression') {
      const params1 = params[0]
      params[0] = params1.replace("'", '$')
      params.push(this.delegate?.getObjectNames())
    }

    // 转换参数类型
    const types = new Array(params.length)
    for (let i = 0; i < params.length; i++) {
      const param = params[i]
      types[i] = param == null ? null : param.constructor
    }

    // 查找对象方法
    const method = this.getMethod(obj, name, types)
    if (!method) {
      let result = '***404***'
      if (obj.constructor.name === 'Object') {
        result = this.callJSONObjectFunction(obj, name, params)
      } else if (obj.constructor.name === 'Array') {
        result = this.callJSONArrayFunction(obj, name, params)
      }
      if (result !== '***404***') {
        return result
      }
      let error = `找不到方法: ${obj.constructor.name}.${name}(`
      // 添加方法参数
      types.forEach(t => {
        error += t ? `${t.name},` : 'null,'
      })
      error += ')'
      throw new ServiceException(error)
    }

    // 调用方法并处理返回值
    const oCall = method.apply(obj, params)
    const result = oCall instanceof Promise ? await oCall : oCall
    // 返回处理后的结果
    return result
  }

  /**
   * 适配JSONObject原生方法
   */
  callJSONObjectFunction (obj, name, params) {
    switch (name) {
      case 'has':
        return Object.prototype.hasOwnProperty.call(obj, params[0])
      case 'put': {
        const key = params[0]
        if (key == null) {
          throw new ServiceException('Null key.')
        }
        const value = params[1]
        if (value !== undefined && value !== null) {
          obj[key] = value
        } else {
          delete obj[key]
        }
        return true
      }
      case 'putAll': {
        const appendArray = params[0]
        for (const key in appendArray) {
          obj[key] = appendArray[key]
        }
        return true
      }
      case 'get': {
        const key = params[0]
        return obj[key]
      }
      case 'opt': {
        const key = params[0]
        return key == null ? null : obj[key]
      }
      case 'remove': {
        const key = params[0]
        return delete obj[key]
      }
      case 'keySet':
        return Object.keys(obj)
      default:
        return '***404***'
    }
  }

  /**
   * 适配JSONArray原生方法
   */
  callJSONArrayFunction (obj, name, params) {
    switch (name) {
      case 'length':
        return obj.length
      case 'put':
        return obj.push(params[0])
      case 'putAll': {
        const appendArray = params[0]
        for (let i = 0; i < appendArray.length; i++) {
          obj.push(appendArray[i])
        }
        return true
      }
      case 'get': {
        const index = params[0]
        const value = obj[index]
        if (value === undefined || value === null) {
          throw new ServiceException(`Array[${index}] not found.`)
        }
        return value
      }
      case 'opt': {
        const index = params[0]
        return index >= 0 && index < obj.length ? obj[index] : null
      }
      case 'remove': {
        const index = params[0]
        return index >= 0 && index < obj.length ? obj.splice(index, 1) : null
      }
      default:
        return '***404***'
    }
  }

  static toJSONString (obj) {
    if (typeof obj === 'string' || typeof obj === 'number') {
      return obj
    }
    const replacer = (key, value) => {
      // 如果是函数，认为它是复杂对象，直接返回函数名
      if (typeof value === 'function') {
        return `Function(${value.name || 'anonymous'})` // 返回函数的名称，或者 'anonymous'
      }
      // 如果是 Vue 组件实例
      if (value instanceof Vue) {
        return `VueComponent(${value.constructor.name})`
      }
      return value
    }
    return JSON.stringify(obj, replacer)
  }

  /**
   * 查找与给定方法名和参数类型匹配的方法
   */
  getMethod (obj, methodName, paramTypes) {
    // 获取对象自身的所有属性名
    let methods = Object.getOwnPropertyNames(obj).filter(prop => typeof obj[prop] === 'function')

    // 获取对象的原型
    let proto = Object.getPrototypeOf(obj)

    // 递归获取原型链上的所有方法
    while (proto !== null) {
      methods = methods.concat(
        Object.getOwnPropertyNames(proto)
          .filter(prop => !['caller', 'callee', 'arguments'].includes(prop)) // 先排除
          .filter(prop => {
            try {
              return typeof proto[prop] === 'function' // 再判断是否为函数
            } catch (e) {
              return false // 避免 TypeError
            }
          })
      )
      proto = Object.getPrototypeOf(proto)
    }

    // 去重
    methods = [...new Set(methods)]

    for (const methodNameInObj of methods) {
      if (methodNameInObj === methodName) {
        const method = obj[methodNameInObj]
        if (this.matchParameterTypes(method, paramTypes)) {
          return method
        }
      }
    }
    return null
  }

  /**
   * 判断方法的参数类型是否与给定的类型匹配
   */
  matchParameterTypes (method, paramTypes) {
    return true
  }

  setDelegate (delegate) {
    this.delegate = delegate
  }

  isNumberC (value) {
    return !isNaN(Number(value)) // 判断 value 是否可以转成有效的数字
  }
}
