import * as ol from 'ol'
import * as style from 'ol/style'
import * as layer from 'ol/layer'
import * as source from 'ol/source'
import * as geom from 'ol/geom'
import {fromCircle} from 'ol/geom/Polygon';
import * as proj from 'ol/proj'
import * as interaction from 'ol/interaction'
import * as coordinate from 'ol/coordinate'
import * as control from 'ol/control'
import * as sphere from 'ol/sphere'
import { unByKey } from 'ol/Observable'
import './measure.scss'
import {createBox} from "ol/interaction/Draw";
import {Circle, LineString, Polygon} from "ol/geom";
import {formatPosition} from '@/utils/easyMap'

const layerFlag = ['layerName', 'drawLayer']
let drawTooltipElement;
let drawHelpTooltipElement;
const typeMapper = new Map([
    ['line', 'LineString'],
    ['rectangle', 'LineString'],
    ['polygon', 'Polygon'],
    ['circle', 'Circle'],
])
let oldDrawFeature
/**
 *
 * @param map
 * @param typeSelect    line线，rectangle矩形，polygon多边形，circle圆形
 */
export default function Draw (map, typeSelect) {
    return new Promise((resolve, reject) => {
        if (!drawTooltipElement) {
            let _source
            const realLayer = map.getLayers().getArray().filter(v => v.get(layerFlag[0]) === layerFlag[1])
            if (realLayer[0]) {
                _source = realLayer[0].getSource()
            } else {
                _source = new source.Vector(); //图层数据源
                const _vector = new layer.Vector({
                    zIndex: 9999,
                    source: _source,
                    style: new style.Style({ //图层样式
                        fill: new style.Fill({
                            color: 'rgba(46,129,255,0.15)' //填充颜色
                        }),
                        stroke: new style.Stroke({
                            color: '#2E81FF',  //边框颜色
                            width: 2   // 边框宽度
                        }),
                        image: new style.Circle({
                            radius: 7,
                            fill: new style.Fill({
                                color: '#ffcc33'
                            })
                        })
                    })
                });
                _vector.set(layerFlag[0], layerFlag[1])
                map.addLayer(_vector);
            }
            let sketch;
            let helpTooltip;
            let measureTooltip;
            let continueMsg = '双击结束标绘';
            const geodesicCheckbox = true;//测地学方式对象
            const createMeasureTooltip = () => {
                const id = 'drawTooltipElementId'
                if (drawTooltipElement) {
                    map.removeOverlay(map.getOverlayById(id))
                    drawTooltipElement.parentNode.removeChild(drawTooltipElement);
                }
                drawTooltipElement = document.createElement('div');
                drawTooltipElement.className = 'tooltip tooltip-measure';
                measureTooltip = new ol.Overlay({
                    id,
                    element: drawTooltipElement,
                    offset: [0, -15],
                    positioning: 'bottom-center'
                });
                map.addOverlay(measureTooltip);
            }
            const createHelpTooltip = () => {
                const id = 'drawHelpTooltipElementId'
                if (drawHelpTooltipElement) {
                    map.removeOverlay(map.getOverlayById(id))
                    drawHelpTooltipElement.parentNode.removeChild(drawHelpTooltipElement);
                }
                drawHelpTooltipElement = document.createElement('div');
                drawHelpTooltipElement.className = 'tooltip hidden';
                helpTooltip = new ol.Overlay({
                    id,
                    element: drawHelpTooltipElement,
                    offset: [15, 0],
                    positioning: 'center-left'
                });
                map.addOverlay(helpTooltip);
            }
            const formatLength = (line) => {
                // 获取投影坐标系
                const sourceProj = map.getView().getProjection();
                // ol/sphere里有getLength()和getArea()用来测量距离和区域面积，默认的投影坐标系是EPSG:3857, 其中有个options的参数，可以设置投影坐标系
                const length = sphere.getLength(line, {projection: sourceProj});
                // const length = getLength(line);
                let output;
                if (length > 100) {
                    const km = Math.round((length / 1000) * 100) / 100;
                    output = `${km} 千米 <br>${parseFloat(String(km * 0.53995)).toFixed(2)} 海里`;
                } else {
                    output = `${Math.round(length * 100) / 100} m`;
                }
                return output;
            };
            //获取圆的面积
            const getCircleArea = (circle, projection) => {
                const P = 3.14
                const radius = getCircleRadius(circle, projection)
                return P * radius * radius
            }
//获取圆的半径
            const getCircleRadius = (circle, projection) => {
                return circle.getRadius() * projection.getMetersPerUnit()
            }
            const formatArea = (polygon, type= 'polygon') => {
                let area
                const sourceProj = map.getView().getProjection();
                // 获取投影坐标系
                if (type === 'polygon') {
                    area = sphere.getArea(polygon, {
                        projection: sourceProj,
                    });
                } else if (type === 'circle') {
                    area = getCircleArea(polygon, sourceProj)
                }
                let output;
                if (area > 10000) {
                    const km = Math.round((area / 1000000) * 100) / 100;
                    output = `${km} 平方公里<br>${parseFloat(String(km * 0.38610)).toFixed(
                      2
                    )} 平方英里`;
                } else {
                    output = `${Math.round(area * 100) / 100} ` + " m<sup>2</sup>";
                }
                return output;
            };
            const addInteraction = () => {
                const id = 'drawName'
                const draw = new interaction.Draw({
                    source: _source,//测量绘制层数据源
                    // @ts-ignore
                    type: typeMapper.get(typeSelect),  //几何图形类型
                    // @ts-ignore
                    geometryFunction: typeSelect === 'rectangle' ? createBox() : null,
                    style: new style.Style({
                        fill: new style.Fill({
                            color: "rgba(46,129,255,0.15)",
                        }),
                        stroke: new style.Stroke({
                            color: "#2E81FF",
                            width: 2,
                        }),
                        image: new style.Circle({
                            radius: 5,
                            stroke: new style.Stroke({
                                color: "rgba(0, 0, 0, 0.7)",
                            }),
                            fill: new style.Fill({
                                color: "rgba(255, 255, 255, 0.2)",
                            }),
                        }),
                    }),
                });
                draw.set(id, id)
                createMeasureTooltip(); //创建测量工具提示框
                createHelpTooltip(); //创建帮助提示框
                map.addInteraction(draw);
                let listener;
                //绑定交互绘制工具开始绘制的事件
                const drawstartHandle = (evt) => {
                    sketch = evt.feature; //绘制的要素
                    let tooltipCoord = evt.coordinate;// 绘制的坐标
                    //绑定change事件，根据绘制几何类型得到测量长度值或面积值，并将其设置到测量工具提示框中显示
                    listener = sketch.getGeometry().on('change', function (evt) {
                        const geom = evt.target
                        let output;
                        if (geom.getType() === 'LineString') {
                            output = formatLength(geom);//长度值
                            tooltipCoord = geom.getLastCoordinate();//坐标
                        } else if (geom.getType() === 'Polygon') {
                            output = formatArea(geom);//面积值
                            tooltipCoord = geom.getInteriorPoint().getCoordinates();//坐标
                        } else if (geom.getType() === 'Circle') {
                            output = formatArea(geom, 'circle');//面积值
                            tooltipCoord = geom.getCenter()
                        }
                        drawTooltipElement.innerHTML = output;//将测量值设置到测量工具提示框中显示
                        measureTooltip.setPosition(tooltipCoord);//设置测量工具提示框的显示位置
                    });
                }
                draw.on('drawstart', drawstartHandle);
                //绑定交互绘制工具结束绘制的事件
                const copy = (value) => {
                    const str = document.createElement('input')
                    str.setAttribute('value', value)
                    document.body.appendChild(str)
                    str.select()
                    document.execCommand('copy')
                    document.body.removeChild(str)
                }
                const drawendHandle = (evt) => {
                    map.removeInteraction(map.getInteractions().getArray().filter(v => v.get(id) === id)[0]);
                    // const del = document.createElement("div");
                    // del.className = "lineDel";
                    // drawTooltipElement.append(del);
                    // del.onclick = () => {
                    //     _source.removeFeature(evt.feature)
                    //     const b = del.parentElement.parentElement
                    //     b.parentElement.removeChild(b);
                    //     const g = evt.feature.getGeometry()
                    //     if (g.getType() === 'LineString') {
                    //         const w = `LINESTRING(${g.getCoordinates().map(v => v[0] + ' ' + v[1]).join(',')})`
                    //         copy(w)
                    //     } else if (g.getType() === 'Polygon') {
                    //         const w = `POLYGON(${g.getCoordinates().map(v => '(' + v.map(c => c[0] + ' ' + c[1]) + ')').join(',')})`
                    //         copy(w)
                    //     }
                    // };
                    // drawTooltipElement.className = 'tooltip tooltip-static'; //设置测量提示框的样式
                    // measureTooltip.setOffset([0, -7]);
                    // 标绘的时候不需要最终结果dom
                    map.removeOverlay(map.getOverlayById('drawHelpTooltipElementId'))
                    drawTooltipElement.parentNode.removeChild(drawTooltipElement);
                    sketch = null; //置空当前绘制的要素对象
                    drawTooltipElement = null; //置空测量工具提示框对象
                    drawHelpTooltipElement.parentNode.removeChild(drawHelpTooltipElement);
                    drawHelpTooltipElement = null; //置空测量工具提示框对象
                    unByKey(listener);
                    draw.un('drawstart', drawstartHandle);
                    draw.un('drawend', drawendHandle);
                    map.removeInteraction(map.getInteractions().getArray().filter(v => v.get(id) === id)[0]);
                    map.un('pointermove', pointerMoveHandler)
                    if (oldDrawFeature) {
                        _source.removeFeature(oldDrawFeature)
                    }
                    oldDrawFeature = evt.feature
                    const gm = oldDrawFeature.getGeometry()
                    let wkt = ''
                    const gType = gm.getType()
                    if (gType === 'Polygon') {
                        wkt = formatPosition.cpnTwpn(gm.getCoordinates())
                    } else if (gType === 'LineString') {
                        wkt = formatPosition.clTwl(gm.getCoordinates())
                    } else if (gType === 'Circle') {
                        const circlePoly = fromCircle(gm, 128)
                        oldDrawFeature.setGeometry(circlePoly)
                        wkt = formatPosition.cpnTwpn(circlePoly.getCoordinates())
                    }
                    resolve({feature: oldDrawFeature, wkt: wkt})
                }
                draw.on('drawend', drawendHandle);
            }
            addInteraction(); //调用加载绘制交互控件方法，添加绘图进行测量
            const pointerMoveHandler = (evt) => {
                if (evt.dragging) {
                    return;
                }
                let helpMsg = '单击开始标绘';//当前默认提示信息
                //判断绘制几何类型设置相应的帮助提示信息
                if (sketch) {
                    const geom = sketch.getGeometry()
                    helpMsg = continueMsg;
                    // if (geom.getType() === 'Polygon') {
                    //     helpMsg = continueMsg; //绘制多边形时提示相应内容
                    // } else if (geom.getType() === 'LineString') {
                    //     helpMsg = continueMsg; //绘制线时提示相应内容
                    // }
                }
                drawHelpTooltipElement.innerHTML = helpMsg; //将提示信息设置到对话框中显示
                helpTooltip.setPosition(evt.coordinate);//设置帮助提示框的位置
                drawHelpTooltipElement.classList.remove('hidden');//移除帮助提示框的隐藏样式进行显示
            };
            map.on('pointermove', pointerMoveHandler); //地图容器绑定鼠标移动事件，动态显示帮助提示框内容
            //地图绑定鼠标移出事件，鼠标移出时为帮助提示框设置隐藏样式
            try {
                map.getViewport().on('mouseout', () => {
                    drawHelpTooltipElement.addClass('hidden');
                });
            } catch (e) {
            }
        } else {
            reject('正在标绘中，请勿重复操作！')
        }
    })
}

export const DrawClear = (map) => {
    const realLayer = map.getLayers().getArray().filter(v => v.get(layerFlag[0]) === layerFlag[1])
    if (realLayer[0]) {
        realLayer[0].getSource().clear()
        oldDrawFeature = null
    }
}
