import DataUtils from '../utils/DataUtils';
import VerifyUtils from '../utils/VerifyUtils';
import GeogUtils from '../utils/GeogUtils';
import PointDrawing from './PointDrawing';
import PolylineDrawing from './PolylineDrawing';
import PolygonDrawing from './PolygonDrawing';
import CircleDrawing from './CircleDrawing';
import RectangleDrawing from './RectangleDrawing';
import GeoJsonProvider from '../geog/GeoJsonProvider';

/**
 * 绘制提供类
 * @alias DrawingProvider
 *
 * @summary <用于动态绘制图形>
 */
export default class DrawingProvider {
    /**
     * 构造函数
     * @param {Object} options -图层选项
     */
    constructor(options) {
        /**
         * 地图对象
         * @type {Object}
         */
        this._map = options.map;

        /**
         * 最小缩放层级
         * @type {Number}
         */
        this._minzoom = DataUtils.default(options.minzoom, 10);

        // 绘制模式 ('point', 'polyline', 'polygon', 'circle', 'rectangle')
        this._drawingMode = 'none';
        // 绘制结果数据集
        this._fc = null;

        /** 绘制类 **/
        this._pointDrawing = null;
        this._polylineDrawing = null;
        this._polygonDrawing = null;
        this._circleDrawding = null;
        this._rectangleDrawing = null;
    }

    /** 公有方法 **/
    /**
     * 绘制
     * @param {String} mode -绘制模式
     * @param {function} callback -回调函数
     */
    draw(mode, callback) {
        // 结束绘制
        this.finish();
        // 清除
        this.clear();

        switch (mode) {
            case 'point': // 点
                this._drawPoint(callback);
                break;
            case 'polyline': // 折线
                this._drawPolyline(false, callback);
                break;
            case 'polygon': // 多边形
                this._drawPolygon(false, callback);
                break;
            case 'circle': // 圆形
                this._drawCircle(callback);
                break;
            case 'rectangle': // 矩形
                this._drawRectangle(callback);
                break;
            default:
                break;
        }
    }

    /**
     * 捕捉
     * @param {String} mode -绘制模式
     * @param {Object} data -捕捉起点数据
     * @param {function} callback -回调函数
     */
    snap(mode, data, callback) {
        // 结束绘制
        this.finish();

        switch (mode) {
            case 'snap-point': // 捕捉画点
                this._snapDrawPoint(data, callback);
                // 清除
                this.clear();
                break;
            case 'snap-polyline': // 捕捉画线
                this._snapDrawPolyline(data, callback);
                break;
            case 'snap-polyline-end': { // 捕捉画线结束
                this._snapEndPolyline(callback);
                // 清除
                this.clear();
                break;
            }
            default:
                break;
        }
    }

    /**
     * 测量
     * @param {String} mode -测量模式
     * @param {function} callback -回调函数
     */
    measure(mode, callback = null) {
        // 结束绘制
        this.finish();
        // 清除
        //this.clear();

        switch (mode) {
            case 'length': // 长度测量
                this._drawPolyline(true, callback);
                break;
            case 'area': // 面积测量
                this._drawPolygon(true, callback);
                break;
            default:
                break;
        }
    }

    /**
     * 结束绘制
     */
    finish() {
        switch (this._drawingMode) {
            case 'point':
            case 'snap-point': { // 点/捕捉画点
                this._pointDrawing && this._pointDrawing.finish();
                this._fc = this._pointDrawing && this._pointDrawing.getData();
                break;
            }
            case 'polyline':
            case 'snap-polyline': { // 折线/捕捉画线
                this._polylineDrawing && this._polylineDrawing.finish();
                this._fc = this._polylineDrawing && this._polylineDrawing.getData();
                break;
            }
            case 'polygon': { // 多边形
                this._polygonDrawing && this._polygonDrawing.finish();
                this._fc = this._polygonDrawing && this._polygonDrawing.getData();
                break;
            }
            case 'circle': { // 圆
                this._circleDrawding && this._circleDrawding.finish();
                this._fc = this._circleDrawding && this._circleDrawding.getData();
                break;
            }
            case 'rectangle': { // 矩形
                this._rectangleDrawing && this._rectangleDrawing.finish();
                this._fc = this._rectangleDrawing && this._rectangleDrawing.getData();
                break;
            }
            default:
                break;
        }

        this._drawingMode = 'none';
    }

    /**
     * 清除
     */
    clear() {
        // 点
        if (this._pointDrawing) {
            this._pointDrawing.clearData();
        }

        // 折线
        if (this._polylineDrawing) {
            this._polylineDrawing.clearData();
        }

        // 多边形
        if (this._polygonDrawing) {
            this._polygonDrawing.clearData();
        }

        // 圆
        if (this._circleDrawding) {
            this._circleDrawding.clearData();
        }

        // 矩形
        if (this._rectangleDrawing) {
            this._rectangleDrawing.clearData();
        }

        if (this._map.getLayer('drawing_polyline')) {
            this._map.removeLayer('drawing_polyline');
        }
        if (this._map.getSource('drawing_polyline')) {
            this._map.removeSource('drawing_polyline');
        }
    }

    /**
     * 移除图层
     */
    removeLayer() {
        // 移除点绘制图层
        if (this._pointDrawing) {
            this._pointDrawing.finish();
            this._pointDrawing.removeLayer();
        }

        // 移除折线绘制图层
        if (this._polylineDrawing) {
            this._polylineDrawing.finish();
            this._polylineDrawing.removeLayer();
        }

        // 移除多边形绘制图层
        if (this._polygonDrawing) {
            this._polygonDrawing.finish();
            this._polygonDrawing.removeLayer();
        }

        // 移除圆形绘制图层
        if (this._circleDrawding) {
            this._circleDrawding.finish();
            this._circleDrawding.removeLayer();
        }

        // 移除矩形绘制图层
        if (this._rectangleDrawing) {
            this._rectangleDrawing.finish();
            this._rectangleDrawing.removeLayer();
        }
    }

    /**
     * 返回要素集
     */
    getData() {
        return this._fc;
    }

    /** 私有方法 **/
    /**
     * 绘制点
     * @param {function} callback -回调函数
     */
    _drawPoint(callback) {
        this._drawingMode = 'point';

        if (!this._pointDrawing) {
            this._pointDrawing = new PointDrawing({
                map: this._map
            });
        }
        // 开始绘制
        this._pointDrawing.draw(callback);
    }

    /**
     * 捕捉画点
     * @param {Object} data -折线数据
     * @param {function} callback -回调函数
     */
    _snapDrawPoint(data, callback) {
        this._drawingMode = 'snap-point';

        const feature = GeoJsonProvider.getEmptyFeature('Point');
        const snapFeature = data;

        if (VerifyUtils.isGeoJsonFeature(snapFeature) &&
                snapFeature.geometry.type === 'LineString') {
            const coordinates = snapFeature.geometry.coordinates;

            const lonLat = snapFeature.properties.lonLat; // 点击的坐标
            // 比较单击的点距离起止点距离
            const startLonLat = coordinates[0];
            const endLonLat = coordinates[coordinates.length - 1];

            let toStartDist = GeogUtils.calcDistance(lonLat, startLonLat);
            let toEndDist = GeogUtils.calcDistance(lonLat, endLonLat);

            const pointLonLat = (toStartDist <= toEndDist) ? startLonLat : endLonLat;
            const inout_type = (toStartDist <= toEndDist) ? 'in' : 'out';

            feature.geometry.coordinates = pointLonLat;
            feature.properties.inout_type = inout_type; // 起止节点类型
        }

        if (!this._pointDrawing) {
            this._pointDrawing = new PointDrawing({
                map: this._map
            });
        }
        // 设置数据
        this._pointDrawing.setData(feature);

        callback(feature);
    }

    /**
     * 绘制折线
     * @param {Boolean} isMeasure -是否测量
     * @param {function} callback -回调函数
     */
    _drawPolyline(isMeasure, callback) {
        this._drawingMode = 'polyline';

        if (!this._polylineDrawing) {
            this._polylineDrawing = new PolylineDrawing({
                map: this._map
            });
        }
        // 开始绘制
        this._polylineDrawing.draw(isMeasure, callback);
    }

    /**
     * 捕捉画线
     * @param {Object} data -点数据
     * @param {function} callback -回调函数
     */
    _snapDrawPolyline(data, callback) {
        this._drawingMode = 'snap-polyline';

        if (!this._polylineDrawing) {
            this._polylineDrawing = new PolylineDrawing({
                map: this._map
            });
        }

        if (data && VerifyUtils.isGeoJsonFeature(data) &&
                data.geometry.type === 'Point') {
            let startLonLat = data.geometry.coordinates;
            // 开始绘制
            this._polylineDrawing.snap(startLonLat, callback);
        } else {
            callback(data);
        }
    }

    /**
     * 捕捉画线结束
     * @param {function} callback -回调函数
     */
    _snapEndPolyline(callback) {
        this._polylineDrawing.snapEnd(callback);
    }

    /**
     * 绘制多边形
     * @param {Boolean} isMeasure -是否测量
     * @param {function} callback -回调函数
     */
    _drawPolygon(isMeasure, callback) {
        this._drawingMode = 'polygon';

        if (!this._polygonDrawing) {
            this._polygonDrawing = new PolygonDrawing({
                map: this._map
            });
        }
        // 开始绘制
        this._polygonDrawing.draw(isMeasure, callback);
    }

    /**
     * 绘制圆
     * @param {function} callback -回调函数
     */
    _drawCircle(callback) {
        this._drawingMode = 'circle';

        if (!this._circleDrawding) {
            this._circleDrawding = new CircleDrawing({
                map: this._map
            })
        }
        // 开始绘制
        this._circleDrawding.draw(callback);
    }

    /**
     * 绘制矩形
     * @param {function} callback -回调函数
     */
    _drawRectangle(callback) {
        this._drawingMode = 'rectangle';

        if (!this._rectangleDrawing) {
            this._rectangleDrawing = new RectangleDrawing({
                map: this._map
            });
        }
        // 开始绘制
        this._rectangleDrawing.draw(callback);
    }

    /**
     * 带预设点数据的绘制
     * @param {String} mode -绘制模式
     * @param {Array} points -预设点位数据 [[lng, lat], ...]
     * @param {function} callback -回调函数
     */
    _drawWithPoints(mode, points, callback) {
        this._drawingMode = mode;

        // 生成统一的 sourceId 和 layerId
        const sourceId = `drawing_${mode}`;
        const layerId = `drawing_${mode}`;
        let geojsonData = GeoJsonProvider.getEmptyFC();

        switch (mode) {
            case 'polyline': { // 折线
                // 创建带预设点的折线
                const feature = GeoJsonProvider.getEmptyFeature('LineString');
                feature.geometry.coordinates = points;

                // 直接组织为 GeoJSON 数据源
                geojsonData = {
                    type: 'FeatureCollection',
                    features: [feature]
                };
                break;
            }
            case 'polygon': { // 多边形
                // 创建带预设点的多边形
                const feature = GeoJsonProvider.getEmptyFeature('Polygon');
                feature.geometry.coordinates = [points];

                // 直接组织为 GeoJSON 数据源
                geojsonData = {
                    type: 'FeatureCollection',
                    features: [feature]
                };
                break;
            }
            case 'point': { // 点
                // 创建带预设点的点要素
                const feature = GeoJsonProvider.getEmptyFeature('Point');
                feature.geometry.coordinates = points.length > 0 ? points[0] : points;

                // 直接组织为 GeoJSON 数据源
                geojsonData = {
                    type: 'FeatureCollection',
                    features: [feature]
                };
                break;
            }
            default:
                // 对于圆、矩形等其他类型，可以直接调用原始绘制方法
                // this.draw(mode, callback);
                break;
        }

        // 设置统一的 sourceId 和 layerId
        if (this._map.getSource(sourceId)) {
            this._map.removeSource(sourceId);
        }
        this._map.addSource(sourceId, {
            type: 'geojson',
            data:  geojsonData
        });

        switch (mode) {
            case 'polyline':
                this._map.addLayer({
                    type: "line",
                    id: layerId,
                    source: sourceId,
                    minzoom: this._minzoom,
                    layout: {
                        visibility: "visible",
                    },
                    paint: {
                        "line-color": "#176BC9",
                        "line-width": 2,
                        "line-opacity": 0.85
                    }
                });
                break;
            case 'polygon':
                this._map.addLayer({
                    type: 'fill',
                    source: sourceId,
                    id: layerId,
                    minzoom: this._minzoom,
                    layout: {
                        visibility: "visible",
                    },
                    paint: {
                        "fill-color": "#00FFF0",
                        "fill-opacity": 0.25,
                    }
                });
                break
            case 'point':
                this._map.addLayer({
                    source: sourceId,
                    id: layerId,
                    type: "circle",
                    minzoom: this._minzoom,
                    layout: {
                        visibility: "visible",
                    },
                    paint: {
                        "circle-radius": 4.5,
                        "circle-color": "#176BC9",
                        "circle-opacity": 0.75,
                        "circle-stroke-width": 2,
                        "circle-stroke-color": "#78B7FF"
                    }
                })
                break
            default:
                console.log('类别暂不支持!')
                break;
        }

        callback && callback();
    }


}
