<template>
  <view class="container">
    <map
      id="map"
      style="width: 100%; height: 100%; z-index: 1"
      :latitude="mapProps.latitude"
      :longitude="mapProps.longitude"
      :markers="markers"
      min-scale="1"
      :scale="mapProps.scale"
      @regionchange="mapChange"
      @updated="mapUpdated"
      @labeltap="tapMarker"
      @markertap="tapMarker"
      :show-scale="true"
    ></map>
    <view class="card" v-if="ready">
      <swiper
        class="mt-68"
        :autoplay="false"
        @change="changeMarker"
        :current="markersIndex"
      >
        <block v-if="!empty">
          <swiper-item v-for="(item, index) in station" :key="index">
            <view class="station">
              <charge-station
                :title="item.StationName"
                :address="item.Address"
                :price="item.TotalFee"
                :fast="item.fastEquipmentInfos"
                :slow="item.slowEquipmentInfos"
                :sId="item.StationID"
                :distance="item.StationLatDistance"
                :latitude="item.StationLat"
                :longitude="item.StationLng"
                :fromMap="true"
              ></charge-station>
            </view>
          </swiper-item>
        </block>
        <block v-else>
          <swiper-item>
            <view class="station">
              <view class="station-empty flex-column flex-align-center pt-20">
                <image src="/static/images/map-empty.png" mode="widthFix" />
                <view class="fs-22 mt-14" style="color: rgba(0, 0, 0, 0.5)"
                  >暂无充电站信息</view
                >
              </view>
            </view>
          </swiper-item>
        </block>
      </swiper>
    </view>
    <view class="icon-menu" v-if="menuStyle.menu1" :style="menuStyle.menu1">
      <view class="flex-center mt-40" @click="search" hover-class="hover">
        <image src="/static/images/map-search.png" mode="widthFix" />
      </view>
      <view
        class="flex-center mt-40"
        @click="toggleDialogVisible"
        hover-class="hover"
      >
        <image src="/static/images/map-filter.png" mode="widthFix" />
      </view>
    </view>
    <view class="icon-menu" v-if="menuStyle.menu2" :style="menuStyle.menu2">
      <view class="flex-center" hover-class="hover" @click="resetLocation">
        <image src="/static/images/map-location.png" mode="widthFix" />
      </view>
    </view>
    <view
      class="dialog"
      v-if="filterDialog.visible"
      @click="toggleDialogVisible"
    >
      <view class="filter-dialog" @click.stop="emptyTap">
        <view :style="filterDialog.style"></view>
        <view class="pl-40 pr-40">
          <view class="pt-20 pb-20">
            <text class="fs-30 fw-500">距离</text>
          </view>
          <view class="flex-wrap pb-14">
            <view
              :class="[
                'type',
                'flex-shrink',
                'flex-center',
                'mt-20',
                (index + 1) % 5 === 0 ? 'mr-0' : 'mr-20',
                `type-${
                  item.value === filterDialog.options.distance ? 'active' : ''
                }`,
              ]"
              v-for="(item, index) in filterDialog.range"
              :key="index"
              @click.stop="changeFilterDistance(index)"
              style="width: 117rpx"
              >{{ item.value }}km</view
            >
          </view>
          <view class="fs-30 fw-500 pt-38 pb-20">充电状态</view>
          <view class="flex pb-30">
            <view
              :class="[
                'type',
                'flex-center',
                'mr-20',
                `type-${index === filterDialog.options.status ? 'active' : ''}`,
              ]"
              v-for="(item, index) in filterDialog.status"
              :key="index"
              @click.stop="changeFilterStatus(index)"
              >{{ item.title }}</view
            >
          </view>
          <view class="foot flex-align-center">
            <style-button size="small" @click.stop="resetFilter"
              >重置</style-button
            >
            <view style="width: 30rpx"></view>
            <style-button size="small" type="primary" @click.stop="submitFilter"
              >确定</style-button
            >
          </view>
        </view>
      </view>
    </view>
  </view>
  <view class="login-mask" v-if="!token">
    <button open-type="getPhoneNumber" @getphonenumber="loginMask" class="full">
      登陆按钮
    </button>
  </view>
</template>

<script setup lang="ts">
const defaulDistance = 3;
const defaultScale = 12;
const pointSize = {
  width: 34,
  height: 58,
  fontSize: 10,
  iconPath: "/static/images/map-point.png",
  currentWidth: 52,
  currentHeight: 86,
  currentFontSize: 11,
  currentIconPath: "/static/images/map-point-current.png",
  androidX: -14,
  androidCurrentX: -20,
};
import { fetchToken, login, onLogin } from "@/api/auth";
import { fetchStations } from "@/api/charge";
import { fetchCollectList } from "@/api/user";
import { fetchLocation } from "@/utils/location";
import { onLoad } from "@dcloudio/uni-app";
import { ref } from "vue";
const isIOS = ref(false);
const token = ref<string>();
const ready = ref(false);
const empty = ref(true);
const mapProps = ref({
  latitude: 23.098994,
  longitude: 113.32252,
  selflatitude: 23.098994,
  selflongitude: 113.32252,
  scale: defaultScale,
});
const filterDialog = ref({
  visible: false,
  style: {},
  range: [
    {
      value: 1,
      scale: defaultScale + 3,
    },
    {
      value: 2,
      scale: defaultScale + 1,
    },
    {
      value: 3,
      scale: defaultScale,
    },
    {
      value: 5,
      scale: defaultScale - 0.2,
    },
    {
      value: 10,
      scale: defaultScale - 0.5,
    },
    {
      value: 20,
      scale: defaultScale - 1.5,
    },
    {
      value: 30,
      scale: defaultScale - 2,
    },
    {
      value: 50,
      scale: defaultScale - 2.5,
    },
    {
      value: 100,
      scale: defaultScale - 3.5,
    },
    {
      value: 200,
      scale: defaultScale - 4.5,
    },
  ],
  options: {
    distance: defaulDistance,
    status: 0,
  },
  status: [
    {
      title: "全部",
    },
    {
      title: "空闲",
    },
    {
      title: "忙碌",
    },
  ],
});
const menuStyle = ref({
  menu1: {},
  menu2: {},
});
const stationPage = ref({
  page: 1,
  pageSize: 6,
  hasNext: false,
});
const station = ref<any[]>([]);
const markersIndex = ref(0);
const markers = ref<any[]>([]);

let isIgnoreChangeLocation = false;

const refreshStation = (location: any) => {
  let length = 0;
  let available = 0;
  const { latitude, longitude } = location;
  return fetchStations(
    stationPage.value.page,
    stationPage.value.pageSize,
    latitude,
    longitude,
    mapProps.value.selflatitude,
    mapProps.value.selflongitude,
    {
      distance: filterDialog.value.options.distance,
      status: filterDialog.value.options.status,
    }
  ).then((res) => {
    const _markersIndex = stationPage.value.page === 1 ? 0 : markersIndex.value;
    const _markers: any[] = res.map((item, index) => {
      length = 0;
      available = 0;
      item.EquipmentInfos &&
        item.EquipmentInfos.forEach((eq: any) => {
          eq.ConnectorInfos &&
            eq.ConnectorInfos.forEach((co: any) => {
              length += 1;
              if (
                co.ConnectorStatusInfo &&
                co.ConnectorStatusInfo.Status === 1
              ) {
                available += 1;
              }
            });
        });
      return {
        id: Number(item.StationID),
        latitude: item.StationLat,
        longitude: item.StationLng,
        iconPath:
          index === _markersIndex
            ? pointSize.currentIconPath
            : pointSize.iconPath,
        width:
          index === _markersIndex ? pointSize.currentWidth : pointSize.width,
        height:
          index === _markersIndex ? pointSize.currentHeight : pointSize.height,
        label: {
          content: `${available}/${length}`,
          color: "#ffffff",
          fontSize:
            index === _markersIndex
              ? pointSize.currentFontSize
              : pointSize.fontSize,
          textAlign: isIOS.value ? "center" : "left",
          anchorX: isIOS.value
            ? 0
            : index === _markersIndex
            ? pointSize.androidCurrentX
            : pointSize.androidX,
          anchorY: -(
            (index === _markersIndex
              ? pointSize.currentHeight
              : pointSize.height) - 3
          ),
        },
      };
    });
    if (stationPage.value.page === 1) {
      _markers.push({
        id: -1,
        latitude: mapProps.value.selflatitude,
        longitude: mapProps.value.selflongitude,
        iconPath: "/static/images/map-current.png",
        width: 34,
        height: 34,
      });
    }
    isIgnoreChangeLocation = true;
    stationPage.value.hasNext = res.length >= stationPage.value.pageSize;
    empty.value = stationPage.value.page === 1 ? res.length <= 0 : false;
    station.value =
      stationPage.value.page === 1 ? res : [...station.value, ...res];
    markersIndex.value = _markersIndex;
    markers.value = _markers;
    return res;
  });
};

const refresh = () => {
  // console.log('刷新电站')
  uni.showLoading({
    title: "加载中",
  });
  stationPage.value.page = 1;
  stationPage.value.hasNext = false;
  station.value = [];
  markers.value = [];
  markersIndex.value = 0;
  filterDialog.value.visible = false;
  fetchLocation()
    .then((res: any) => {
      mapProps.value.latitude = res.latitude;
      mapProps.value.longitude = res.longitude;
      mapProps.value.selflatitude = res.latitude;
      mapProps.value.selflongitude = res.longitude;
      isIgnoreChangeLocation = true;
      return refreshStation(res);
    })
    .then(() => {
      uni.hideLoading();
      ready.value = true;
    })
    .catch((err) => {
      console.log(err);
      uni.hideLoading();
      uni.showModal({
        content: `${err.errMsg},请重试`,
      });
    });
};

onLoad((query: any) => {
  // 只为了打包进tab-bar使用
  console.log(fetchToken, login, onLogin);
  // 扫普通码
  if (query.q) {
    getApp<any>().globalData.normalCode = decodeURIComponent(query.q); // 获取到二维码原始链接内容
  }
  const menu = uni.getMenuButtonBoundingClientRect();
  const window = uni.getWindowInfo();
  const device = uni.getSystemInfoSync();
  isIOS.value = device.osName === "ios";
  menuStyle.value.menu1 = `top:${menu.top + menu.height}px;right:${
    window.windowWidth - menu.right
  }px;`;
  menuStyle.value.menu2 = `bottom:420rpx;right:${
    window.windowWidth - menu.right
  }px;margin-bottom: constant(safe-area-inset-bottom);margin-bottom: env(safe-area-inset-bottom);`;
  filterDialog.value.style = `height:${menu.bottom + 6}px;`;
  setTimeout(() => {
    token.value = getApp<any>().globalData.token || "";
    if (!token.value) {
      fetchLocation().then((res: any) => {
        mapProps.value.latitude = res.latitude;
        mapProps.value.longitude = res.longitude;
        mapProps.value.selflatitude = res.latitude;
        mapProps.value.selflongitude = res.longitude;
        markers.value = [
          {
            id: -1,
            latitude: res.latitude,
            longitude: res.longitude,
            iconPath: "/static/images/map-current.png",
            width: 34,
            height: 34,
          },
        ];
      });
      onLogin((_token) => {
        if (getApp<any>().globalData.normalCode) {
          const code: string = getApp<any>().globalData.normalCode;
          getApp<any>().globalData.normalCode = "";
          getApp<any>().deCode(code);
        }
        token.value = _token;
        fetchCollectList().then(() => {
          refresh();
        });
      });
      return;
    }
    fetchCollectList().then(() => {
      if (getApp<any>().globalData.normalCode) {
        const code: string = getApp<any>().globalData.normalCode;
        getApp<any>().globalData.normalCode = "";
        getApp<any>().deCode(code);
      }
      refresh();
    });
  }, 300);
});

const toggleDialogVisible = () => {
  filterDialog.value.visible = !filterDialog.value.visible;
};
const changeFilterDistance = (index: number) => {
  filterDialog.value.options.distance = filterDialog.value.range[index].value;
};
const changeFilterStatus = (index: number) => {
  filterDialog.value.options.status = index;
};
const resetFilter = () => {
  filterDialog.value.options.distance = defaulDistance;
  filterDialog.value.options.status = 0;
  refresh();
};
const submitFilter = () => {
  const findIndex = filterDialog.value.range.findIndex(
    (item) => item.value === filterDialog.value.options.distance
  );
  if (mapProps.value.scale === filterDialog.value.range[findIndex].scale) {
    filterDialog.value.visible = false;
    refresh();
    return;
  }
  filterDialog.value.visible = false;
  mapProps.value.scale = filterDialog.value.range[findIndex].scale;
};
const resetLocation = () => {
  // eslint-disable-next-line promise/catch-or-return
  fetchLocation().then((res: any) => {
    const mapCtx = uni.createMapContext("map");
    const { latitude, longitude } = res;
    mapCtx.moveToLocation({
      latitude,
      longitude,
    });
    mapProps.value.scale = defaultScale;
  });
};
const mapUpdated = (e: any) => {
  setTimeout(() => {
    isIgnoreChangeLocation = false;
  }, 500);
};
const mapChange = (e: any) => {
  if (isIgnoreChangeLocation) {
    return;
  }
  if (e.type === "end" && markers.value.length) {
    // console.log("refreshStation");
    const { latitude, longitude } = e.detail.centerLocation;
    stationPage.value.page = 1;
    refreshStation({
      latitude,
      longitude,
    });
  }
};
const _changeMarker = (current: number) => {
  const _markers = JSON.parse(JSON.stringify(markers.value));
  const markersNewIndex = current;
  _markers[markersIndex.value].iconPath = pointSize.iconPath;
  _markers[markersIndex.value].width = pointSize.width;
  _markers[markersIndex.value].height = pointSize.height;
  _markers[markersIndex.value].label.fontSize = pointSize.fontSize;
  _markers[markersIndex.value].label.anchorY = -(pointSize.height - 3);
  if (!isIOS) {
    _markers[markersIndex.value].label.anchorX = pointSize.androidX;
  }

  _markers[markersNewIndex].iconPath = pointSize.currentIconPath;
  _markers[markersNewIndex].width = pointSize.currentWidth;
  _markers[markersNewIndex].height = pointSize.currentHeight;
  _markers[markersNewIndex].label.fontSize = pointSize.currentFontSize;
  _markers[markersNewIndex].label.anchorY = -(pointSize.currentHeight - 3);
  if (!isIOS) {
    _markers[markersNewIndex].label.anchorX = pointSize.androidCurrentX;
  }

  isIgnoreChangeLocation = true;
  markers.value = _markers;
  markersIndex.value = markersNewIndex;
  if (stationPage.value.hasNext && markersNewIndex >= _markers.length - 2) {
    stationPage.value.page += 1;
    refreshStation({
      latitude: mapProps.value.selflatitude,
      longitude: mapProps.value.selflongitude,
    });
  }
};
const changeMarker = (e: any) => {
  _changeMarker(e.detail.current);
};
const tapMarker = (e: any) => {
  if (e.detail.markerId === -1) {
    return;
  }
  const findIndex = station.value.findIndex(
    (item) => Number(item.StationID) === Number(e.detail.markerId)
  );
  if (findIndex >= 0) {
    _changeMarker(findIndex);
  }
};
const search = () => {
  uni.navigateTo({
    url: "/pages-charge/search/search",
  });
};
const loginMask = (e: any) => {
  login(e);
};
const emptyTap = () => {};
</script>

<style lang="scss">
@import "../../styles/dialog.scss";
page {
  background-color: #ffffff;
}

.container {
  position: relative;
  height: 100vh;
  width: 100vw;
  background-color: #ffffff;
}

.login-mask {
  position: fixed;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  z-index: 999999;
  opacity: 0;

  .full {
    width: 100%;
    height: 100%;
  }
}

.icon-menu {
  position: absolute;
  z-index: 9;

  image {
    width: 60rpx;
  }

  & > view {
    height: 96rpx;
    width: 96rpx;
    border-radius: 50%;
    background-color: #fff;
    box-shadow: 0px 8rpx 20rpx rgba(0, 0, 0, 0.2);
  }

  .hover {
    box-shadow: none;
  }
}

.filter-dialog {
  background-color: #fff;

  .slider {
    position: relative;
    height: 12rpx;
    width: 100%;
    border-radius: 8rpx;
    background-color: var(--color-sec);
    margin-top: 10rpx;

    &_active {
      position: absolute;
      left: 0;
      top: 0;
      background-color: var(--color-primary);
      border-radius: 8rpx;
      height: 12rpx;
      width: 0%;
    }

    &_block {
      position: absolute;
      width: 40rpx;
      height: 40rpx;
      border-radius: 50%;
      top: -15rpx;
      left: 0;
      background: rgba(255, 255, 255, 1);
      box-shadow: 0px 4rpx 6rpx rgba(52, 125, 255, 0.4);
    }

    &_wx {
      position: absolute;
      width: 100%;
      left: 0px;
      top: -5px;
      margin: 0;
      opacity: 0;
    }
  }

  .type {
    width: 160rpx;
    height: 60rpx;
    background: var(--color-sec);
    border-radius: 4rpx;
    color: var(--color-gray);
    font-size: 26rpx;
    border: 1px solid var(--color-sec);
  }

  .type-active {
    border: 1px solid var(--color-primary);
    color: var(--color-primary);
  }

  .foot {
    height: 120rpx;
    border-top: 1rpx solid var(--color-sec);
  }
}

.card {
  position: absolute;
  width: 100%;
  height: 450rpx;
  left: 0px;
  bottom: 0rpx;
  z-index: 9;
  background: linear-gradient(180deg, rgba(87, 104, 133, 0) 0%, #576885 100%);
  padding-left: 10rpx;
  margin-bottom: constant(safe-area-inset-bottom);
  margin-bottom: env(safe-area-inset-bottom);

  swiper,
  swiper-item {
    width: 100%;
    height: 300rpx;
  }

  .station {
    width: 100%;
    height: 100%;
    padding: 0rpx 20rpx;
  }

  .station-empty {
    width: 100%;
    height: 100%;
    background-color: #fff;
    border-radius: 20rpx 20rpx 0 0;
    image {
      width: 160rpx;
    }
  }
}
</style>
