<template>
  <div class="easy-map-ol">
    <div class="map" ref="ref_easyMapOl"/>
    <template v-if="layout === 'info'">
      <div class="easy-map_ol-info_tips">
        <div class="easy-map_ol-info-scaleLine" ref="ref_easyMap_scaleLine"></div>
        <div class="easy-map_ol-info-info">
          <div @click="controlMousePosition.format = !controlMousePosition.format">经度：{{controlMousePosition.format ? controlMousePosition.formatLongitude : controlMousePosition.longitude}}</div>
          <div @click="controlMousePosition.format = !controlMousePosition.format">纬度：{{controlMousePosition.format ? controlMousePosition.formatLatitude : controlMousePosition.latitude}}</div>
          <div>层级：
            <div class="easy-map_ol-info-zoom">
              <div class="easy-map_ol-info-zoom-button easy-map_ol-info-zoom-button_min __hover" @click="zoomChange(false)">-</div>
              <div class="easy-map_ol-info-zoom-num">{{Math.floor(interactionZoom)}}</div>
              <div class="easy-map_ol-info-zoom-button easy-map_ol-info-zoom-button_max __hover" @click="zoomChange(true)">+</div>
            </div>
          </div>
        </div>
      </div>
    </template>
    <template v-else>
      <div class="easy-map_ol-default-mouse-position" ref="ref_easyMap_olMousePosition" @click="controlMousePosition.format = !controlMousePosition.format">
        <template v-if="controlMousePosition.format">
          {{controlMousePosition.formatLongitude}}<br/>
          {{controlMousePosition.formatLatitude}}
        </template>
        <template v-else>
          {{controlMousePosition.longitude}}<br/>
          {{controlMousePosition.latitude}}
        </template>
      </div>
      <div class="easy-map_ol-default-zoom" ref="ref_easyMap_olZoom">
        <div class="easy-map_ol-default-zoom-button" @click="zoomChange(true)">+</div>
        <div class="easy-map_ol-default-zoom-num">{{Math.floor(interactionZoom)}}</div>
        <div class="easy-map_ol-default-zoom-button" @click="zoomChange(false)">-</div>
      </div>
      <div class="easy-map_ol-default-scaleLine" ref="ref_easyMap_scaleLine"></div>
    </template>
  </div>
</template>

<script lang="ts">
  import {
    defineComponent,
    onMounted,
    ref,
    toRefs,
    reactive,
    watch,
    getCurrentInstance,
    ComponentInternalInstance,
    computed,
    nextTick, onActivated,
  } from "vue";
  import { useStore } from "vuex";
  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 * as proj from 'ol/proj'
  import * as interaction from 'ol/interaction'
  import * as coordinate from 'ol/coordinate'
  import * as control from 'ol/control'
  import InitMapInfoClass from "./initMapInfo";

  export default defineComponent({
    name: "",
    components: {
    },
    props: {
      baseMapLayers: { default: () => [] },
      baseMapView: {},
      layout: {}
    },
    setup(props, { emit }) {
      const store = useStore();
      const that = (getCurrentInstance() as ComponentInternalInstance).appContext.config.globalProperties;
      const state = reactive({
        controlMousePosition: {
          longitude: <any>null,
          latitude: <any>null,
          format: true,
          formatLongitude: <any>null,
          formatLatitude: <any>null,
        },
        interactionZoom: props.baseMapView.zoom,
        realBaseLayers: null,
      });
      const easyMapOl = ref()
      const ref_easyMapOl = ref()
      const ref_easyMap_olMousePosition = ref()
      const ref_easyMap_olZoom = ref()
      const ref_easyMap_scaleLine = ref()
      const initMap = () => {
        state.realBaseLayers = props.baseMapLayers.map(v => InitMapInfoClass.isInternet ? InitMapInfoClass.initInternet(v) : InitMapInfoClass.initBaseLayer(v))
        easyMapOl.value = new ol.Map({
          target: ref_easyMapOl.value,
          layers: [
            new layer.Group({
              _easyMapOl_layerGroupType: 'base',
              layers: state.realBaseLayers,
              zIndex: 1
            }),
          ],
          view: new ol.View(props.baseMapView),
          controls: control.defaults({
            attribution: false,
            rotate: false,
            zoom: false,
          }).extend([
            new control.MousePosition({
              target: ref_easyMap_olMousePosition.value,
              coordinateFormat: (e) => {
                state.controlMousePosition.longitude = e[0].toFixed(6)
                state.controlMousePosition.latitude = e[1].toFixed(6)
                const f = coordinate.toStringHDMS(e, 0).split(' ')
                state.controlMousePosition.formatLatitude = `${f[0]} ${f[1]} ${f[2]} ${f[3]}`
                state.controlMousePosition.formatLongitude = `${f[4]} ${f[5]} ${f[6]} ${f[7]}`
                return null
              },
              placeholder: ''
            }),
            new control.Zoom({
              target: ref_easyMap_olZoom.value,
            }),
            new control.ScaleLine({
              target: ref_easyMap_scaleLine.value,
              bar: true
            })
          ]),
          interactions: interaction.defaults({
            doubleClickZoom: false
          })
        })
        easyMapOl.value.getView().on('change:resolution', e => {
          state.interactionZoom = e.target.getZoom()
          emit('olZoomChange', state.interactionZoom)
        })
        const defaultBaseLayer = state.realBaseLayers.filter(v => v.getVisible())[0]
        setLayerView(defaultBaseLayer)
        emit('olMapLoad', easyMapOl.value)
        easyMapOl.value.on('contextmenu', e => {
          window.event.returnValue = false
          if (window?.event?.shiftKey) {
            const str = document.createElement('input')
            str.setAttribute('value', `POINT(${e.coordinate[0]} ${e.coordinate[1]})`)
            document.body.appendChild(str)
            str.select()
            document.execCommand('copy')
            document.body.removeChild(str)
          }
        })
      }
      const zoomChange = (flag) => {
        state.interactionZoom = flag ? state.interactionZoom + 1 : state.interactionZoom - 1
        if (state.interactionZoom > easyMapOl.value.getView().getMaxZoom()) {
          state.interactionZoom = easyMapOl.value.getView().getMaxZoom()
        } else if (state.interactionZoom < easyMapOl.value.getView().getMinZoom()) {
          state.interactionZoom = easyMapOl.value.getView().getMinZoom()
        }
        easyMapOl.value.getView().setZoom(state.interactionZoom)
      }
      const baseLayersMap = computed(() => {
        const map = new Map()
        easyMapOl.value?.getLayers().getArray().filter(v => v.get('_easyMapOl_layerGroupType') === 'base')[0].getLayers().getArray().forEach(v => {
          map.set(v.get('_easyMapOl_layerName'), v)
        })
        return map
      })
      const switchBaseLayer = (layerName) => {
        baseLayersMap.value.forEach((v, k) => {
          if (layerName === k) {
            setLayerView(v)
            v.setVisible(true)
          } else {
            v.setVisible(false)
          }
        })
      }
      const setLayerView = (_layer) => {
        easyMapOl.value.getView().setMaxZoom(_layer.get('_maxZoom'))
        easyMapOl.value.getView().setMinZoom(_layer.get('_minZoom'))
      }
      const refresh = () => {
        easyMapOl.value.updateSize();
        easyMapOl.value.render()
      }
      onMounted(() => {
        nextTick(() => {
          initMap()
          setTimeout(() => {
            refresh()
          })
        })
      })
      return {
        ...toRefs(state),
        ref_easyMapOl,
        ref_easyMap_olMousePosition,
        ref_easyMap_olZoom,
        ref_easyMap_scaleLine,
        easyMapOl,
        zoomChange,
        switchBaseLayer,
        baseLayersMap,
        refresh,
      }
    },
  });
</script>
<style scoped lang="scss">
.easy-map-ol {
  width: 100%;
  height: 100%;
  position: relative;
  .map {
    width: 100%;
    height: 100%;
    background-color: #bfdbf3;
  }
  ::v-deep(.ol-zoom) {
    display: none;
  }
  ::v-deep(.ol-scale-bar-inner) {
    position: absolute;
    bottom: 1%;
    left: 1%;
    &>div>div:nth-child(2) {
      .ol-scale-singlebar {
        border-left: 2px solid #807A7A;
      }
    }
    &>div>div:nth-child(5) {
      .ol-scale-singlebar {
        border-right: 2px solid #807A7A;
      }
    }
    .ol-scale-step-text {
      padding-bottom: 20px;
      font-size: 12px;
      transform: scale(0.8);
      position: absolute;
      bottom: -5px;
      font-size: 12px;
      z-index: 11;
      color: #000000;
      width: max-content;
      text-shadow: -2px 0 #ffffff,
      0 2px #ffffff,
      2px 0 #ffffff,
      0 -2px #ffffff;
    }
    .ol-scale-singlebar {
      border: 0;
      background-color: transparent !important;
      border-bottom: 2px solid #807A7A;
      height: 10px;
    }
    .ol-scale-step-marker {
      display: none;
    }
  }
  .easy-map_ol-info_tips {
    position: absolute;
    z-index: 1;
    right: 10px;
    bottom: 10px;
    display: flex;
    .easy-map_ol-info-info {
      background-color: rgba(255, 255, 255, 0.5);
      border-radius: 6px;
      color: #333333;
      font-size: 12px;
      padding: 6px;
      >div {
        display: flex;
        align-items: center;
      }
      .easy-map_ol-info-zoom {
        display: flex;
        align-items: center;
        .easy-map_ol-info-zoom-num {
          line-height: 1;
          padding: 1px 10px;
          border: 1px solid rgba(51, 51, 51, 0.51);
        }
        .easy-map_ol-info-zoom-button {
          padding: 0 3px;
          &.easy-map_ol-info-zoom-button_max {
            color: #356de7;
          }
        }
      }
    }
    .easy-map_ol-info-scaleLine {
      width: 160px;
    }
  }
  .easy-map_ol-default-mouse-position {
    cursor: pointer;
    position: absolute;
    z-index: 1;
    color: #000;
    top: unset;
    font-size: 14px;
    right: 10px;
    bottom: 10px;
    height: 50px;
    padding: 5px 10px;
    background-color: #fff;
    border-radius: 2px;
    line-height: 22px;
    opacity: .8;
  }
  .easy-map_ol-default-zoom {
    position: absolute;
    bottom: 70px;
    right: 10px;
    >div {
      display: flex;
      align-items: center;
      justify-content: center;
      margin: 0;
      padding: 0;
      color: #000;
      font-size: 12px;
      font-weight: 700;
      height: 20px;
      width: 20px;
      background-color: #fff;
    }
    .easy-map_ol-default-zoom-num {
      border-top: 1px solid rgba(153, 153, 153, 0.32);
      border-bottom: 1px solid rgba(153, 153, 153, 0.32);
    }
    .easy-map_ol-default-zoom-button {
      cursor: pointer;
      &:hover {
        opacity: 0.7;
      }
    }
  }
  .easy-map_ol-default-scaleLine {
    position: absolute;
    bottom: 20px;
    left: 20px;
  }
}
</style>
