    import { BaseServer } from '../..'
    import { Log, defaultValue } from '../../../util'
    import { Zondy } from '../../../base'
    import { checkParam } from '../../Utils'
    import { createWorkflow } from './index'

    /**
     * 工作流服务,基地址http://{ip}:{port}/igs/rest/services/workflow/{serviceName}/WorkflowServer
     * @class WorkFlowServer
     * @moduleEx ServerModule
     * @extends BaseServer
     * @param {Object} options 构造参数
     * @param {String} [options.url ] 服务基地址，必传
     * @see [<h4>不同工作流参数配置</h4>]{@tutorial 工作流}
     * @example
     * // 以下以“根据参照系名称进行投影转换”工作流举例,其他工作流用法请参考前文中“不同工作流参数配置”
     * const workflow = WorkFlowServer.createWorkFlow({
     *   url: "http://localhost:8089/igs/rest/services/workflow/600235/WorkflowServer",
     *    clsName: "gdbp://MapGISLocalPlus/test/sfcls/湖泊",
     *    desClsName: `gdbp://MapGISLocalPlus/test/sfcls/湖泊${Math.random()}`,
     *   crsName: "高斯大地坐标系_西安80_36带3_北",
     *   });
     */
    class WorkFlowServer extends BaseServer {
      constructor(options) {
        super(options)
      }

      /**
       * @description 根据工作流id创建工作流
       * @param {Object} 工作流参数
       * @return {WorkFlowServer}
       * @example
       * const workflow = WorkFlowServer.createWorkFlow({
       *   url: "http://localhost:8089/igs/rest/services/workflow/600235/WorkflowServer",
       *    clsName: "gdbp://MapGISLocalPlus/test/sfcls/湖泊",
       *    desClsName: `gdbp://MapGISLocalPlus/test/sfcls/湖泊${Math.random()}`,
       *   crsName: "高斯大地坐标系_西安80_36带3_北",
       *   });
       */
      static createWorkFlow(options) {
        return createWorkflow(options)
      }

      /**
       * @description 获取执行工作流check对象
       * @private
       * @return {Object}
       */
      _getCheckQueryOpts() {
        return {}
      }

      /**
       * @description 获取执行工作流check对象
       * @private
       * @param {Object} 获取工作流参数
       * @return {Object}
       */
      _getWorkflowParameters(checkQueryOpts) {
        const parameters = {}
        const keys = Object.keys(checkQueryOpts)
        keys.forEach((key) => {
          try {
            const value = this[key]
            if (typeof value === 'undefined') {
              Log.error('传入参数错误！')
              return
            }
            if (value && value.clone) {
              parameters[key] = value.clone()
            } else {
              parameters[key] = value
            }
          } catch (err) {
            Log.error(err)
          }
        })
        return parameters
      }

      /**
       * @description 转换check后数据对象
       * @private
       * @param {Object} options 工作流参数
       * @param {Object} checkQueryOpts 工作流检核参数
       * @return {Object}
       */
      _processParams(options, checkQueryOpts) {
        const parameters = {}
        const keys = Object.keys(checkQueryOpts)
        keys.forEach((key) => {
          try {
            let value = options[key]
            let paramName = key
            if (checkQueryOpts[key] && checkQueryOpts[key].process) {
              const checkOptions = checkQueryOpts[key]
              if (typeof checkOptions.process === 'function') {
                value = checkOptions.process(value)
              } else {
                value = checkOptions.process
              }
            }

            if (checkQueryOpts[key] && checkQueryOpts[key].alias) {
              paramName = checkQueryOpts[key].alias
            }
            parameters[paramName] = value
          } catch (err) {
            Log.error(err)
          }
        })
        return parameters
      }

      /**
       * 根据接口的PATH PARAMETERS和QUERY PARAMETERS来发起查询
       * @private
       * @param {Object} options 查询参数
       * @param {Object} pathCheck 要检查的路径参数
       * @param {Object} queryCheck 要检查的查询参数
       * @param {Function} callback 处理请求基地址的回调
       * @return {Boolean} 是否验证通过
       * */
      _queryByParameters(options, pathCheck, queryCheck, callback) {
        options = defaultValue(options, {})

        // 检查PathParameters参数
        const checkPath = this._checkPathParameters(options, pathCheck)
        if (!checkPath.succeed) {
          if (options.failure && options.failure instanceof Function) {
            options.failure({
              succeed: false,
              msg: checkPath.msg,
              data: undefined,
              errorType: checkPath.errorType
            })
          }
          return Promise.reject({
            succeed: false,
            msg: checkPath.msg,
            data: undefined,
            errorType: checkPath.errorType
          })
        }

        if (callback && callback instanceof Function) {
          // 获取url
          const url = callback(this.url, options)
          const checkResult = checkParam(options, queryCheck)
          const parameters = this._processParams(options, queryCheck)
          if (checkResult) {
            checkResult.queryString = `&parameters=${JSON.stringify(parameters)}`
          }
          Log.info('发起请求，基地址为：', url)
          return this._checkAndRequest(checkResult, url, options)
        }
      }

      /**
       * @description 同步执行工作流，返回执行结果
       * @param {Object} options
       * @param {String} [options.headers ] 请求头参数
       * @param {String} [options.method = FetchMethod.get ] 请求类型
       * @param {Function} [options.success ] 查询成功回调函数，若使用Promise方式则不必填写
       * @param {Function} [options.failure ] 查询失败回调函数，若使用Promise方式则不必填写
       * @return {Promise<Object>}
       * @example
        workflow.execute({
          method: Zondy.Enum.FetchMethod.get,
          success: function (res) {
            console.log("execute: ", res);
          },
        });
       */
      execute(options) {
        const opt = options || {}
        // 设置PATH PARAMETERS校验
        const checkPathOpts = {}

        // 设置QUERY PARAMETERS校验
        const checkQueryOpts = this._getCheckQueryOpts()

        // 设置返回
        const parameters = this._getWorkflowParameters(checkQueryOpts)

        // 调用基类的查询信息方法
        return this._queryByParameters(
          Object.assign(parameters, opt),
          checkPathOpts,
          checkQueryOpts,
          // 拼装返回基地址
          function (url) {
            return `${url}/execute?f=json`
          }
        )
      }

      /**
       * @description 异步执行工作流，返回执行任务id
       * @param {Object} options
       * @param {String} [options.headers ] 请求头参数
       * @param {String} [options.method = FetchMethod.get ] 请求类型
       * @param {Function} [options.success ] 查询成功回调函数，若使用Promise方式则不必填写
       * @param {Function} [options.failure ] 查询失败回调函数，若使用Promise方式则不必填写
       * @return {Promise<String>}
        workflow.submit({
          method: Zondy.Enum.FetchMethod.get,
          success: function (res) {
            console.log("submit: ", res);
          },
        });
       */
      submit(options) {
        const opt = options || {}
        // 设置PATH PARAMETERS校验
        const checkPathOpts = {}

        // 设置QUERY PARAMETERS校验
        const checkQueryOpts = this._getCheckQueryOpts()

        // 设置返回
        const parameters = this._getWorkflowParameters(checkQueryOpts)

        // 调用基类的查询信息方法
        return this._queryByParameters(
          Object.assign(parameters, opt),
          checkPathOpts,
          checkQueryOpts,
          // 拼装返回基地址
          function (url) {
            return `${url}/submit?f=json`
          }
        )
      }

      /**
       * @description 查询工作流执行状态
       * @param {Object} options
       * @param {String} [options.taskId] 工作流任务id,必传
       * @param {String} [options.headers ] 请求头参数
       * @param {String} [options.method = FetchMethod.get ] 请求类型
       * @param {Function} [options.success ] 查询成功回调函数，若使用Promise方式则不必填写
       * @param {Function} [options.failure ] 查询失败回调函数，若使用Promise方式则不必填写
       * @return {Promise<String>}
       * @example
        workflow.queryTaskStatus({
          taskId: taskId,
          success: function (res) {
            console.log("success: ", res);
          },
        });
       */
      queryTaskStatus(options) {
        // 设置PATH PARAMETERS校验
        const checkPathOpts = {
          taskId: {
            type: 'String'
          }
        }

        // 设置QUERY PARAMETERS校验
        const checkQueryOpts = {}

        // 调用基类的查询信息方法
        return this._queryByParameters(
          options,
          checkPathOpts,
          checkQueryOpts,
          // 拼装返回基地址
          function (url, options) {
            return `${url}/${options.taskId}?f=json`
          }
        )
      }

      /**
       * @description 查询工作流执行结果
       * @param {Object} options
       * @param {String} [options.taskId] 工作流任务id,必传
       * @param {String} [options.headers ] 请求头参数
       * @param {String} [options.method = FetchMethod.get ] 请求类型
       * @param {Function} [options.success ] 查询成功回调函数，若使用Promise方式则不必填写
       * @param {Function} [options.failure ] 查询失败回调函数，若使用Promise方式则不必填写
       * @return {Promise<String>}
       * @example
        workflow.queryTaskResult({
          taskId: taskId,
          success: function (res) {
            console.log("success: ", res);
          },
        });
       */
      queryTaskResult(options) {
        // 设置PATH PARAMETERS校验
        const checkPathOpts = {
          taskId: {
            type: 'String'
          }
        }

        // 设置QUERY PARAMETERS校验
        const checkQueryOpts = {}

        // 调用基类的查询信息方法
        return this._queryByParameters(
          options,
          checkPathOpts,
          checkQueryOpts,
          // 拼装返回基地址
          function (url, options) {
            return `${url}/${options.taskId}/results?f=json`
          }
        )
      }
    }
    Zondy.Service.WorkFlowServer = WorkFlowServer
    export default WorkFlowServer