    import Zondy from '../Zondy'
    import Evented from '../Evented'
    import { getGUID, defaultValue, Log, defined } from '../../util'
    import { Geometry } from '../geometry'
    import {
      SimpleFillSymbol,
      SimpleLineSymbol,
      SimpleMarkerSymbol,
      Symbol
    } from '../symbol'
    import { GeometryType, SymbolType } from '../enum'

    /**
     * 要素对象，示例如下：<a id='add-Feature'>[初始化要素对象]</a>
     * <br><br>[ES5引入方式]：<br/>
     * Zondy.Feature() <br/>
     * [ES6引入方式]：<br/>
     * import { Feature } from "@mapgis/webclient-common" <br/>
     * <br/>
     * @class Feature
     * @moduleEX BaseModule
     * @param {Object} options 构造参数
     * @param {String} [options.id] 要素的id，不给则给一个随机的默认id
     * @param {Object} [options.attributes = {}] 要素的属性
     * @param {Geometry} [options.geometry] 要素的几何对象，支持如下：<br/>
     * [圆]{@link Circle}、[矩形范围]{@link Extent}、[线]{@link LineString}、
     * [多线]{@link MultiLineString}、[点]{@link Point}、[多点]{@link MultiPoint}、[区]{@link Polygon}、
     * [多区]{@link MultiPolygon}
     * @param {Symbol} [options.symbol = {}] 要素的样式，支持如下：<br/>
     * [图片Marker符号]{@link PictureMarkerSymbol}、[简单Marker符号]{@link SimpleMarkerSymbol}、
     * [简单填充符号]{@link SimpleFillSymbol}、[简单线符号]{@link SimpleLineSymbol}、[文本符号]{@link TextSymbol}
     * @param {Boolean} [options.visible = true] 要素是否可见
     *
     * @summary <h5>支持如下方法：</h5>
     * <a href='#fromGeoJSON'>[1、从geoJSON对象中导入数据]</a><br/>
     * <a href='#toGeoJSON'>[2、导出为GeoJSON数据]</a><br/>
     * <a href='#fromJSON'>[3、通过传入的json构造并返回一个新的几何对象]</a><br/>
     * <a href='#toJSON'>[4、导出一个JSON对像]</a><br/>
     * <a href='#clone'>[5、克隆并返回新要素]</a><br/>
     * <a href='#toIGSFeature'>[6、导出为igs服务接口的要素对象]</a><br/>
     * <a href='#toOldIGSFeature'>[7、出为igs1.0服务接口的要素对象]</a><br/>
     * <a href='#toGraphicInfo'>[8、导出为igs1.0的要素的图形信息]</a><br/>
     * <a href='#toAttValue'>[9、导出为igs1.0的要素的属性值]</a><br/>
     * <a href='#toFType'>[10、导出为igs1.0的要素的几何类型]</a><br/>
     *
     * @example <caption><h7 id='add-Feature'>创建几何对象</h7></caption>
     * // ES5引入方式
     * const { Feature, Color } = Zondy
     * const { LineString } = Zondy.Geometry
     * const { SimpleLineSymbol } = Zondy.Symbol
     * // ES6引入方式
     * import { Feature, Color, LineString, SimpleLineSymbol } from "@mapgis/webclient-common"
     * let feature = new Feature({
     *   //不填则创建一个随机的guid
     *   id: "你的id",
     *   //设置属性
     *   attributes: {},
     *   //构建几何
     *   geometry: new LineString({
     *     coordinates: [[112.0, 30.0], [113.0, 30.0], [113.0, 31.0]]
     *   }),
     *   //设置样式
     *   symbol: new SimpleLineSymbol({
     *     //设置颜色
     *     color: new Color(255, 0, 0, 1),
     *     //设置线宽
     *     width: 2
     *   })
     * })
     */
    class Feature extends Evented {
      constructor(options) {
        super(options)
        options = defaultValue(options, {})
        /**
         * 要素id
         * default 随机id
         * @member {String} Feature.prototype.id
         */
        this.id = defaultValue(options.id, getGUID())
        /**
         * 要素的属性
         * default {}
         * @member {Object} Feature.prototype.attributes
         */
        this.attributes = defaultValue(options.attributes, {})
        /**
         * 要素的几何对象
         * @member {Geometry} Feature.prototype.geometry
         */
        this.geometry = this._decorate(
          'geometry',
          options.geometry,
          Geometry,
          Geometry.fromJSON
        )
        if (!this.geometry) {
          Log.error('要素几何信息缺失')
        }
        /**
         * 要素的样式
         * @member {Symbol} Feature.prototype.symbol
         */
        this.symbol = this._decorate(
          'symbol',
          options.symbol,
          Symbol,
          this._getSymbol.bind(this)
        )
        /**
         * 要素是否可见
         * default = true
         * @member {Boolean} Feature.prototype.visible
         */
        this.visible = defaultValue(options.visible, true)
        /**
         * 对象类型
         * @readonly
         * @member {String} Feature.prototype.type
         */
        this.type = 'Feature'
      }

      /**
       * @description: 根据几何类型支持程度重设符号
       * @param {*} symbol
       * @return symbol
       */
      _getSymbol(symbol) {
        const symbolType = symbol ? symbol.type : 'undefine'
        const geometryType = this.geometry.type
        let instance = symbol instanceof Symbol ? symbol : Symbol.fromJSON(symbol)
        switch (geometryType) {
          case GeometryType.multiPoint:
          case GeometryType.point: {
            const limits = [
              SymbolType.simpleMarker,
              SymbolType.text,
              SymbolType.pictureMarker
            ]
            if (!defined(symbol)) {
              instance = new SimpleMarkerSymbol()
            }
            if (!limits.some((v) => v === symbolType)) {
              Log.info('图元几何和符号不匹配')
              instance = new SimpleMarkerSymbol(instance.toJSON())
            }
            break
          }
          case GeometryType.multiLineString:
          case GeometryType.lineString: {
            const limits = [SymbolType.simpleLine]
            if (!defined(symbol)) {
              instance = new SimpleLineSymbol()
            }
            if (!limits.some((v) => v === symbolType)) {
              Log.info('图元几何和符号不匹配')
              instance = new SimpleLineSymbol(instance.toJSON())
            }

            break
          }
          case GeometryType.polygon:
          case GeometryType.extent:
          case GeometryType.circle:
          case GeometryType.multiPolygon: {
            const limits = [
              SymbolType.simpleFill,
              SymbolType.simpleMarker,
              SymbolType.text,
              SymbolType.pictureMarker
            ]
            if (!defined(symbol)) {
              instance = new SimpleFillSymbol()
            }
            if (!limits.some((v) => v === symbolType)) {
              Log.info('图元几何和符号不匹配')
              instance = new SimpleFillSymbol(instance.toJSON())
            }

            break
          }
          default: {
            break
          }
        }
        return instance
      }

      /**
       * 克隆并返回新要素<a id='clone'></a>
       * @return {Feature} 克隆后的新要素
       */
      clone() {
        return new Feature(this.toJSON())
      }

      /**
       * 导出一个JSON对像<a id='toJSON'></a>
       * @return {Object} JSON对像
       */
      toJSON() {
        const json = {}
        json.id = this.id
        json.attributes = JSON.parse(JSON.stringify(this.attributes))
        json.geometry = this.geometry.toJSON()
        json.symbol = this.symbol.toJSON()
        json.visible = this.visible
        json.type = this.type
        return json
      }

      /**
       * 通过传入的json构造并返回一个新的几何对象<a id='fromJSON'></a>
       * @param {Object} json JSON对象
       * @example <caption><h7>通过传入的json构造并返回一个新的几何对象</h7></caption>\
       * // ES5引入方式
       * const { LineString } = Zondy.Geometry
       * const { Feature } = Zondy
       * // ES6引入方式
       * import { LineString, Feature } from "@mapgis/webclient-common"
       * const json = {
       *   //设置属性
       *   attributes: {},
       *   //构建几何
       *   geometry: new LineString({
       *     coordinates: [[112.0, 30.0], [113.0, 30.0], [113.0, 31.0]]
       *   })
       * }
       * const feature = new Feature.fromJSON(json)
       */
      static fromJSON(json) {
        json = defaultValue(json, {})
        return new Feature(json)
      }

      /**
       * 从geoJSON对象中导入数据<a id='fromGeoJSON'></a>
       * @param geoJSON geoJSON数据
       * @example <caption><h7 id='fromJSON'>从geoJSON对象中导入数据</h7></caption>
       * // ES5引入方式
       * const { Feature } = Zondy
       * // ES6引入方式
       * import { Feature } from "@mapgis/webclient-common"
       * //数据格式参考https://geojson.org/
       * const feature = new Feature();
       * feature.fromGeoJSON({
       *   type: "Feature",
       *   geometry: {
       *     type: "LineString",
       *     coordinates: [
       *       [114.329481, 30.711953],
       *       [114.342372, 30.684553],
       *       [114.341474, 30.674527],
       *       [114.338273, 30.665863],
       *       [114.334533, 30.655893],
       *       [114.330017, 30.643386],
       *       [114.322936, 30.631171],
       *       [114.318749, 30.625032],
       *       [114.313923, 30.617818],
       *       [114.308156, 30.608404],
       *       [114.301348, 30.598718],
       *       [114.295038, 30.592581],
       *       [114.285992, 30.585234],
       *       [114.278415, 30.580865],
       *       [114.270119, 30.577433],
       *       [114.261901, 30.573909],
       *       [114.250444, 30.571547],
       *       [114.240741, 30.574025],
       *       [114.224975, 30.580306],
       *       [114.218822, 30.585491],
       *       [114.211532, 30.589347],
       *       [114.20474, 30.593382],
       *       [114.196667, 30.597536],
       *       [114.183062, 30.604521],
       *       [114.169464, 30.609907],
       *       [114.163868, 30.615064],
       *       [114.155941, 30.61846],
       *       [114.138907, 30.617699],
       *       [114.128567, 30.624968],
       *       [114.123644, 30.631684],
       *       [114.120804, 30.649056],
       *       [114.120828, 30.659055],
       *     ],
       *   },
       *   properties: {
       *     ln: "1号线",
       *     su: "1",
       *     kn: "轨道交通1号线",
       *     ls: "420100034364",
       *     cl: "3080B7",
       *     la: "",
       *     x: 1,
       *     li: "420100034364|420100034365",
       *     color: "#3080B7",
       *   },
       * });
       */
      fromGeoJSON(geoJSON) {
        geoJSON = defaultValue(geoJSON, {})
        const that = this
        // 从geometry中获取几何
        const geometry = defaultValue(geoJSON.geometry, {})
        that.geometry = Geometry.fromGeoJSON(geometry)
        // 从properties中获取属性
        const properties = defaultValue(geoJSON.properties, {})
        Object.keys(properties).forEach(function (key) {
          if (properties.hasOwnProperty(key)) {
            that.attributes[key] = properties[key]
          }
        })
      }

      /**
       * 导出为GeoJSON数据<a id='toGeoJSON'></a>
       * @return geoJSON geoJSON数据
       * @example <caption><h7 id='toGeoJSON'>导出为GeoJSON数据</h7></caption>
       * //导出为GeoJSON数据
       * let geojson = feature.toGeoJSON();
       */
      toGeoJSON() {
        return {
          type: 'Feature',
          geometry: this.geometry.toGeoJSON(),
          properties: JSON.parse(JSON.stringify(this.attributes)),
          style: this.symbol.toJSON()
        }
      }

      /**
       * 导出为igs服务接口的要素对象<a id='toIGSFeature'></a>
       * @return igs传输要素
       */
      toIGSFeature() {
        const geometry = this.geometry.toJSON()
        return {
          type: 'Feature',
          geometry: {
            type: geometry.type,
            coordinates: geometry.coordinates
          },
          attributes: JSON.parse(JSON.stringify(this.attributes)),
          styleInfo: null
        }
      }

      /**
       * 出为igs1.0服务接口的要素对象<a id='toOldIGSFeature'></a>
       * @return igs1.0的要素
       */
      toOldIGSFeature() {
        return {
          fGeom: this.geometry.toOldIGSGeometry(),
          GraphicInfo: this.toGraphicInfo(),
          AttValue: this.toAttValue(),
          FID: this.id,
          bound: null,
          ftype: this.toFType()
        }
      }

      /**
       * 导出为igs1.0的要素的图形信息<a id='toGraphicInfo'></a>
       * @return {Object} igs1.0的要素的图形信息
       */
      toGraphicInfo() {
        let graphicInfo

        switch (this.geometry.type) {
          case 'Point':
          case 'MultiPoint':
            graphicInfo = {
              InfoType: 1,
              PntInfo: this.symbol
            }
            break
          case 'LineString':
          case 'MultiLineString':
            graphicInfo = {
              InfoType: 2,
              LinInfo: this.symbol
            }
            break
          case 'Polygon':
          case 'MultiPolygon':
          default:
            graphicInfo = {
              InfoType: 3,
              RegInfo: this.symbol
            }
            break
        }

        return graphicInfo
      }

      /**
       * 导出为igs1.0的要素的属性值<a id='toAttValue'></a>
       * @return {Array} igs1.0的要素的属性值
       */
      toAttValue() {
        const attValue = []
        const self = this

        Object.keys(this.attributes).forEach((key) => {
          if (self.attributes.hasOwnProperty(key)) {
            attValue.push(self.attributes[key])
          }
        })

        return attValue
      }

      /**
       * 导出为igs1.0的要素的几何类型<a id='toFType'></a>
       * @return {Number} igs1.0的要素的几何类型
       */
      toFType() {
        let ftype

        switch (this.geometry.type) {
          case 'Point':
          case 'MultiPoint':
            ftype = 1
            break
          case 'LineString':
          case 'MultiLineString':
            ftype = 2
            break
          case 'Polygon':
          case 'MultiPolygon':
          default:
            ftype = 3
            break
        }

        return ftype
      }
    }

    Zondy.Feature = Feature
    export default Feature