    import {extend, Zondy,notNULL} from "../common";
    import {ArcGisGeometry}  from "./Geometry";
    import {ArcGisPoint} from "./Point";
    import * as T from '@turf/turf'
    import * as H from '@turf/helpers'

    /**
     * @class module:ArcGis.ArcGisExtent
     * @description ArcGisExtent对象
     * @author 基础平台-杨琨
     * @param options - {Object} 必选项，构造Extent对象参数。
     * @param {String} [query.xmin] 可选项，x轴最小坐标。
     * @param {String} [query.ymin] 可选项，x轴最大坐标。
     * @param {String} [query.ymin] 可选项，y轴最小坐标。
     * @param {String} [query.ymax] 可选项，y轴最小坐标。
     * @param {String} [query.zmin] 可选项，z轴最小坐标。
     * @param {String} [query.zmax] 可选项，z轴最小坐标。
     * @param {String} [query.mmin] 可选项，m轴最小坐标。
     * @param {String} [query.mmax] 可选项，m轴最小坐标。
     */

    class ArcGisExtent extends ArcGisGeometry{
        constructor(options) {
            super(options);
            this.center = undefined;
            this.hasM = false;
            this.hasZ = false;
            this.height = 0;
            this.mmax = undefined;
            this.mmin = undefined;
            this.type = "extent";
            this.width = 0;
            this.xmax = 0;
            this.xmin = 0;
            this.ymax = 0;
            this.ymin = 0;
            this.zmax = undefined;
            this.zmin = undefined;
            this.extent = this;

            //确保私有变量不能被options修改
            this.private = ["center","hasM","hasZ","height","width","type","extent"];
            for (let key in this.private){
                if(notNULL(options[this.private[key]])){
                    throw new Error("[accessor] cannot assign to read-only property '" + this.private[key] + "' of ArcGisExtent");
                }
            }

            extend(this,options);

            //如果z、m有值，hasZ、hasM采薇true
            if(this.zmax || this.zmin){
                this.hasZ = true;
            }
            if(this.mmax || this.mmin){
                this.hasM = true;
            }

            //生成bbox
            this._extentPolygon = T.polygon([[
                [this.xmin, this.ymin],
                [this.xmin, this.ymax],
                [this.xmax, this.ymax],
                [this.ymax, this.ymin],
                [this.xmin, this.ymin]
            ]],{name:"_extentPlygon"});

            //生成中心点
            this.center = initCenter(this);

            //计算width，height
            this.width = this.xmax - this.xmin;
            this.height = this.ymax - this.ymin;
        }
    }

    function initCenter(me){
        let points = [
            H.point( [me.xmin, me.ymin]),
            H.point( [me.xmin, me.ymax]),
            H.point( [me.xmax, me.ymax]),
            H.point( [me.ymax, me.ymin]),
            H.point( [me.xmin, me.ymin])
        ];
        let featureCollection = H.featureCollection(points);
        let coordinates = T.center(featureCollection).geometry.coordinates;
        return new ArcGisPoint({
            longitude: coordinates[0],
            latitude: coordinates[1]
        });
    }

    /**
     * @function module:ArcGis.ArcGisExtent.prototype.equals
     * @description 比较两个Extent对象是否相等
     * @param extent - {ArcGisExtent} 必选项，要比较的ArcGisExtent对象。
     * @returns Boolean，对象是否相等
     */
    ArcGisExtent.prototype.equals = function (extent){
        return this.mmax === extent.mmax &&
            this.mmin === extent.mmin &&
            this.xmax === extent.xmax &&
            this.xmin === extent.xmin &&
            this.ymax === extent.ymax &&
            this.ymin === extent.ymin &&
            this.zmax === extent.zmax &&
            this.zmin === extent.zmin;
    }

    /**
     * @function module:ArcGis.ArcGisExtent.prototype.contains
     * @description 判断是否包含一个点或者一个ArcGisExtent对象
     * @param geometry - {Geometry} 必选项，要比较的ArcGisExtent对象或者ArcGisPoint对象。
     * @returns Boolean，是否包含
     */
    ArcGisExtent.prototype.contains = function (geometry){
        if(geometry.type === "point"){
            let point = geometry.toArray();
            point = T.point([point[0], point[1]]);
            return T.booleanContains(this._extentPolygon,point)
        }
        if(geometry.type === "extent"){
            return T.booleanContains(this._extentPolygon,geometry._extentPolygon)
        }
        return false;
    }

    /**
     * @function module:ArcGis.ArcGisExtent.prototype.expand
     * @description 根据输入的值，扩大或缩小一个ArcGisExtent
     * @param factor - {Number} 必选项，放大或缩小系数。
     * @returns ArcGisExtent，缩放后的ArcGisExtent
     */
    ArcGisExtent.prototype.expand = function (factor){
        if(factor instanceof Number){
            factor = Math.abs(factor);
            this.width = this.width * factor;
            this.height = this.height * factor;
            this.xmin = this.center.x - this.width / 2;
            this.xmax = this.center.x + this.width / 2;
            this.ymin = this.center.y - this.height / 2;
            this.ymax = this.center.y + this.height / 2;
            return this;
        }else {
            throw new Error("require is not defined");
        }
    }

    /**
     * @function module:ArcGis.ArcGisExtent.prototype.intersects
     * @description 比较点、多点、线、多边形、extent是否与当前extent相交
     * @param geometry - {Geometry} 必选项，要比较的几何对象。
     * @returns Boolean，是否相交
     */
    ArcGisExtent.prototype.intersects = function (geometry){
        if(!geometry.type){
            return false;
        }
        let geom;
        if(geometry.type === "polyline"){
            geom = H.multiLineString(geometry.paths);
        }else if(geometry.type === "point"){
            geom = H.point(geometry.toArray());
        }else if(geometry.type === "multipoint"){
            geom = H.multiPoint(geometry.points);
        }else if(geometry.type === "extent"){
            geom = geometry._extentPolygon;
        }else if(geometry.type === "polygon"){
            geom = H.polygon(geometry.rings);
        }
        return !T.booleanDisjoint(geom,this._extentPolygon);
    }

    /**
     * @function module:ArcGis.ArcGisExtent.prototype.offset
     * @description 根据输入的dx, dy, dz值，平移extend
     * @param dx - {Number} 必选项，要平移的x值。
     * @param dx - {Number} 必选项，要平移的y值。
     * @param dx - {Number} 必选项，要平移的z值。
     * @returns ArcGisExtent，平移后的ArcGisExtent对象
     */
    ArcGisExtent.prototype.offset = function (dx, dy, dz){
        this.xmax += dx;
        this.xmin += dx;
        this.ymax += dy;
        this.ymin += dy;
        if(this.hasZ){
            this.zmax += dz;
            this.zmin += dz;
        }else {
            this.hasZ = true;
            this.zmax = 0;
            this.zmin = 0;
        }
        return this;
    }

    /**
     * @function module:ArcGis.ArcGisExtent.prototype.centerAt
     * @description 根据输入的ArcGisPoint对象，生成衣蛾新的中心点
     * @param point - {ArcGisPoint} 必选项，新的中心点。
     * @returns ArcGisExtent
     */
    ArcGisExtent.prototype.centerAt = function (point){
        if(point instanceof ArcGisPoint){
            this.center = new ArcGisPoint({
                longitude: point.x,
                latitude: point.y
            });
            this.xmin = this.center.x - this.width / 2;
            this.xmax = this.center.x + this.width / 2;
            this.ymin = this.center.y - this.height / 2;
            this.ymax = this.center.y + this.height / 2;
            return this;
        }
    }

    ArcGisExtent.prototype.normalize = function (){
        return [this];
    }

    /**
     * @function module:ArcGis.ArcGisExtent.prototype.union
     * @description 输入一个ArcGisExtent对象，与原extent对象合并，生成一个新的extent
     * @param extent - {ArcGisExtent} 必选项，要合并的ArcGisExtent对象。
     * @returns ArcGisExtent，新的Extent对象
     */
    ArcGisExtent.prototype.union = function (extent){
        let cur = this.center;
        let nex = extent.center;
        if(((nex.x - cur.x) > 0 && (nex.y - cur.y) > 0) || ((nex.x - cur.x) === 0 && (nex.y - cur.y) > 0)
            || ((nex.x - cur.x) === 0 && (nex.y - cur.y) === 0)
            || ((nex.x - cur.x) > 0 && (nex.y - cur.y) === 0)){
            this.xmax = extent.xmax;
            this.ymax = extent.ymax;
        }else if((nex.x - cur.x) > 0 && (nex.y - cur.y) < 0 || ((nex.x - cur.x) === 0 && (nex.y - cur.y) < 0)){
            this.xmax = extent.xmax;
            this.ymin = extent.ymin;
        }else if((nex.x - cur.x) < 0 && (nex.y - cur.y) < 0){
            this.xmin = extent.xmin;
            this.ymin = extent.ymin;
        }else if((nex.x - cur.x) < 0 && (nex.y - cur.y || ((nex.x - cur.x) < 0 && (nex.y - cur.y) < 0)) === 0){
            this.xmin = extent.xmin;
            this.ymax = extent.ymax;
        }
        this.center = initCenter(this);
        //计算width，height
        this.width = this.xmax - this.xmin;
        this.height = this.ymax - this.ymin;
        return this;
    }

    /**
     * @function module:ArcGis.ArcGisExtent.prototype.toString
     * @description 返回如下格式的字符串："xmin,ymin,xmax,ymax"
     * @returns Sting
     */
    ArcGisExtent.prototype.toString = function (){
        return this.xmin + "," + this.ymin + "," + this.xmax + "," + this.ymax;
    }

    export {ArcGisExtent};
    Zondy.Service.ArcGisExtent = ArcGisExtent;