'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _regenerator = require('babel-runtime/regenerator');

var _regenerator2 = _interopRequireDefault(_regenerator);

var _asyncToGenerator2 = require('babel-runtime/helpers/asyncToGenerator');

var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2);

var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');

var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);

var _createClass2 = require('babel-runtime/helpers/createClass');

var _createClass3 = _interopRequireDefault(_createClass2);

var _assign = require('lodash/assign');

var _assign2 = _interopRequireDefault(_assign);

var _hat = require('hat');

var _hat2 = _interopRequireDefault(_hat);

var _methodsUtil = require('../../_util/methods-util');

var _arcgisToGeojsonUtils = require('@esri/arcgis-to-geojson-utils');

var _arcgisQuery = require('./arcgisQuery');

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }

var defaultQueryOptions = {
  // 返回结果模式，可选值：[ result | count | ids ]
  mode: 'result',
  // 图层关联显示字段的快捷关键词搜索，如设置[filters]属性则忽略；
  text: null,
  // 查询图层的默认Object ID属性，多个以逗号分割
  objectIds: null,
  // 空间参考
  srs: null,
  // 输出空间参考
  outSRS: null,
  // 输出的属性字段
  outFields: null,
  // 几何空间关系
  spatialRel: 'SpatialRelIntersects',
  // 是否返回空间Geometry数据
  returnGeometry: true,
  // 指定允许最大偏差范围
  maxAllowableOffset: null,
  // GeoQuery的关系参数
  relationParam: null
};

/**
 * 获取GeoQuery的选项
 */
/**
 * @文件说明: Query.GeoQuery - GeoQuery服务
 * @创建人: pjtools@vip.qq.com
 * @创建时间: 2020-03-30 10:40:52
 */

var getGeoQueryParams = function getGeoQueryParams(options) {
  var params = {};
  !(0, _methodsUtil.isEmpty)(options.text) && (params.text = options.text);
  params.inSR = !(0, _methodsUtil.isEmpty)(options.srs) ? options.srs : '';
  params.outSR = !(0, _methodsUtil.isEmpty)(options.outSRS) ? options.outSRS : params.inSR;
  params.outFields = !(0, _methodsUtil.isEmpty)(options.outFields) ? options.outFields : '';
  params.spatialRel = options.spatialRel || defaultQueryOptions.spatialRel;
  params.returnGeometry = (0, _methodsUtil.isBooleanFlase)(options.returnGeometry) ? false : true;
  !(0, _methodsUtil.isEmpty)(options.relationParam) && (params.relationParam = options.relationParam);
  !(0, _methodsUtil.isEmpty)(options.objectIds) && (params.objectIds = options.objectIds);
  !(0, _methodsUtil.isEmpty)(options.maxAllowableOffset) && (params.maxAllowableOffset = options.maxAllowableOffset);
  params.mode = !(0, _methodsUtil.isEmpty)(options.mode) && ['count', 'ids', 'result'].indexOf(options.mode) !== -1 ? options.mode : 'result';
  params.returnIdsOnly = params.mode === 'ids' || params.mode === 'count' ? true : false;
  params.f = 'json';
  return params;
};

/**
 * 查询过滤条件进行数据转换
 */
var getQueryFilters = function getQueryFilters(options) {
  if ((0, _methodsUtil.isNotEmptyArray)(options.filters)) {
    var toQueryFilters = function toQueryFilters(filters) {
      var where = null;
      var geometryWhere = null;
      var logical = filters[0] && filters[0].toUpperCase();
      // 判断过滤条件是否为复合逻辑条件
      if (logical && ['AND', 'OR'].indexOf(logical) !== -1) {
        var condition = [];
        for (var i = 1, len = filters.length; i < len; i++) {
          if ((0, _methodsUtil.isNotEmptyArray)(filters[i])) {
            var result = toQueryFilters(filters[i]);
            result.where && condition.push(result.where);
            result.geometryWhere && (geometryWhere = result.geometryWhere);
          }
        }
        if ((0, _methodsUtil.isNotEmptyArray)(condition)) {
          var xfilters = [];
          condition.map(function (item) {
            xfilters.push('(' + item + ')');
          });
          where = xfilters.join(' ' + logical + ' ');
        }
      } else {
        // 判断过滤条件是否为一般逻辑条件
        if (logical && ['==', '!=', '<', '>', '<=', '>=', '..', 'BETWEEN', '~', 'LIKE', 'NULL', '*'].indexOf(logical) !== -1) {
          // 根据类型设置属性
          switch (logical) {
            case '==':
              where = filters[1] + ' = ' + (0, _arcgisQuery.toArcgisFilterValue)(filters[2], filters[3]);
              break;
            case '!=':
              where = filters[1] + ' != ' + (0, _arcgisQuery.toArcgisFilterValue)(filters[2], filters[3]);
              break;
            case '<':
              where = filters[1] + ' < ' + filters[2];
              break;
            case '>':
              where = filters[1] + ' > ' + filters[2];
              break;
            case '<=':
              where = filters[1] + ' <= ' + filters[2];
              break;
            case '>=':
              where = filters[1] + ' >= ' + filters[2];
              break;
            case '..':
            case 'BETWEEN':
              where = filters[1] + ' BETWEEN ' + (0, _arcgisQuery.toArcgisFilterValue)(filters[2], filters[4]) + ' AND ' + (0, _arcgisQuery.toArcgisFilterValue)(filters[3], filters[4]);
              break;
            case '~':
            case 'LIKE':
              where = filters[1] + ' LIKE \'' + (filters[2].indexOf('%') !== -1 ? filters[2] : '%' + filters[2] + '%') + '\'';
              where = where.replace(/\%/g, '%25');
              break;
            case 'NULL':
              where = filters[1] + ' IS NULL';
              break;
            case '*':
              where = '' + String(filters[1]).replace(/"/g, '\'');
              break;
          }
        } else if (logical && ['BBOX', 'POINT', 'LINE', 'PATH', 'POLYGON'].indexOf(logical) !== -1) {
          // 根据类型设置空间属性
          switch (logical) {
            case 'BBOX':
              geometryWhere = {
                geometryType: 'GeometryEnvelope',
                geometry: { xmin: filters[1][0][0], ymin: filters[1][0][1], xmax: filters[1][1][0], ymax: filters[1][1][1] }
              };
              break;
            case 'POINT':
              geometryWhere = {
                geometryType: 'GeometryPoint',
                geometry: { x: filters[1][0], y: filters[1][1] }
              };
              break;
            case 'LINE':
            case 'PATH':
              geometryWhere = {
                geometryType: 'GeometryPolyline',
                geometry: { paths: [filters[1]] }
              };
              break;
            case 'POLYGON':
              geometryWhere = {
                geometryType: 'GeometryPolygon',
                geometry: { rings: filters[1] }
              };
              break;
          }
        }
      }
      return { where: where, geometryWhere: geometryWhere };
    };
    return toQueryFilters(options.filters);
  }
  return null;
};

var GeoQuery = function () {
  function GeoQuery() {
    (0, _classCallCheck3['default'])(this, GeoQuery);
  }

  (0, _createClass3['default'])(GeoQuery, [{
    key: 'queryTask',

    /**
     * 发送GeoQuery服务任务，获取指定过滤条件的GeoJSON要素数据集合
     * @param {String} url 服务地址
     * @param {String} typeName 要素图层标识名
     * @param {Object} options 解析服务的参数选项
     */
    value: function () {
      var _ref = (0, _asyncToGenerator3['default'])( /*#__PURE__*/_regenerator2['default'].mark(function _callee(url) {
        var typeName = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
        var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
        var opts;
        return _regenerator2['default'].wrap(function _callee$(_context) {
          while (1) {
            switch (_context.prev = _context.next) {
              case 0:
                opts = (0, _assign2['default'])({}, defaultQueryOptions, options);
                return _context.abrupt('return', new Promise(function (resolve, reject) {
                  // 获取查询服务的参数选项
                  var params = getGeoQueryParams(opts);
                  // 获取查询过滤条件
                  var filters = getQueryFilters(opts, params);
                  if (filters) {
                    params.where = filters.where || '';
                    if (filters.geometryWhere && filters.geometryWhere.geometry) {
                      params.geometry = filters.geometryWhere.geometry;
                      params.geometryType = filters.geometryWhere.geometryType || 'esriGeometryEnvelope';
                    }
                  } else {
                    params.where = 'OID<=10';
                  }
                  // 判断是否为统计模式
                  if (params.mode === 'count') {
                    params.where = 'OID>=0';
                    params.geometry = '';
                    params.returnGeometry = false;
                  }
                  // 发送查询请求任务
                  var errorMsg = 'GeoQuery\u67E5\u8BE2\u670D\u52A1[ ' + url + ' ]\u8981\u7D20\u6570\u636E\u89E3\u6790\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5[filters]\u8FC7\u6EE4\u6761\u4EF6\u6216\u5C5E\u6027\u4FE1\u606F\u7B49\u662F\u5426\u6709\u8BEF.';
                  (0, _methodsUtil.fetchPostJson)(url.replace(/\/MapServer/g, '/MapServer/' + typeName + '/query'), params).then(function (data) {
                    switch (params.mode) {
                      case 'count':
                        {
                          resolve(data && data.objectIds && data.objectIds.length || 0);
                          break;
                        }
                      case 'ids':
                        {
                          resolve(data && data.objectIds ? data.objectIds : []);
                          break;
                        }
                      default:
                        {
                          var geojson = {
                            type: 'FeatureCollection',
                            features: []
                          };
                          var xdata = (0, _arcgisToGeojsonUtils.arcgisToGeoJSON)(data);
                          if (xdata && xdata.features) {
                            xdata.features.map(function (f) {
                              f.id = opts.idField ? f.properties[opts.idField].toString() : (0, _hat2['default'])();
                              geojson.features.push(f);
                            });
                          }
                          resolve(geojson);
                          break;
                        }
                    }
                  })['catch'](function (e) {
                    console.error(errorMsg);
                    reject();
                  });
                }));

              case 2:
              case 'end':
                return _context.stop();
            }
          }
        }, _callee, this);
      }));

      function queryTask(_x3) {
        return _ref.apply(this, arguments);
      }

      return queryTask;
    }()
  }]);
  return GeoQuery;
}();

exports['default'] = GeoQuery;