<template>
  <div 
    class="light-map"
    :class="{ 
      'full': full ,
      'small': small
    }" 
    @click="emit('mapClick')"
  >
    <slot />
    <map 
      id="prevMap"
      map-id="prevMap"
      class="light-map-map"
      :style="{
        pointerEvents: small ? 'none' : undefined
      }"
      :show-location="true"
      :enable-poi="!small"
      :scale="12"
      :longitude="lonlat?.longitude"
      :latitude="lonlat?.latitude"
      @markertap="onMarkerTap" 
    />

    <!-- 状态显示 -->
    <FlexCol v-if="mapLoader.error.value" 
      gap="gap.md" 
      position="absolute" 
      inset="0"
      center 
    > 
      <FlexCol center gap="gap.md" padding="padding.md" backgroundColor="white" radius="radius.md">
        <Icon name="warning" size="44" color="red" />
        <Text textAlign="center" :text="mapLoader.error.value" />
      </FlexCol>
    </FlexCol>
    <FlexCol v-else-if="mapLoader.status.value === 'loading'" 
      gap="gap.md" 
      position="absolute" 
      inset="0" 
      center
    > 
      <ActivityIndicator :size="64" />
    </FlexCol>

    <!-- 导航栏 -->
    <FlexCol 
      position="absolute" 
      :inset="{ l: 0, b: 0,r: 0 }"
      :zIndex="20"
      :padding="full ? [0, 10] : 20"
    >
      <FlexRow align="center" justify="space-between">
        <view v-if="small"></view>
        <template v-else>
          <BoxMid direction="row" wrap gap="gap.md" align="center" :padding="15">
            <NButton
              :text="city + ' ▼'"
              color="transparent"
              type="custom"
              :radius="30"
              :padding="30"
              :textProps="{
                maxWidth: 150,
                lines: 1
              }"
              @click="emit('changeCity')" 
            />
            <SimpleDropDownPicker
              class="light-map-region-picker" 
              backgroundColor="transparent"
              :modelValue="selectedRegion" 
              @update:modelValue="onSelectedRegion"
              :columns="regionLoader.content.value" 
            />
            <SimpleDropDownPicker
              class="light-map-region-picker" 
              backgroundColor="transparent"
              v-model:modelValue="lightState" 
              :columns="[
                {
                  id: 1,
                  name: '点亮状态',
                },
                {
                  id: 2,
                  name: '已点亮',
                },
                {
                  id: 3,
                  name: '未点亮',
                },
              ]" 
            />
            
            <FrameButton
              icon="search" 
              size="small"
              @click="showSearch" 
            />
            <FrameButton
              icon="navigation" 
              size="small"
              @click="emit('getCurrentLonlat')" 
            />
            <Width />
          </BoxMid>
        </template>
      </FlexRow>
      <StatusBarSpace v-if="full" />
    </FlexCol>

    <!-- 上下渐变遮罩 -->
    <BackgroundBox 
      v-if="full"
      position="fixed" 
      :inset="{ l: 0, t: 0, r: 0 }"
      :height="500"
      :zIndex="19"
      color2="transparent"
      color1="white"
    />
    <BackgroundBox 
      v-if="full"
      position="fixed" 
      :inset="{ l: 0, b: 0, r: 0 }"
      :zIndex="19"
      :height="300"
      color1="transparent"
      color2="white"
    />
  </div>
</template>

<script setup lang="ts">
import { computed, getCurrentInstance, onMounted, ref, watch } from 'vue';
import { assertNotNull, waitTimeOut } from '@imengyu/imengyu-utils';
import { toast } from '@/components/dialog/CommonRoot';
import { useSimpleDataLoader } from '@/components/composeabe/loader/SimpleDataLoader';
import LightVillageApi, { type VillageMapItem } from '@/api/light/LightVillageApi';
import AppCofig from '@/common/config/AppCofig';
import SimpleDropDownPicker from '@/common/components/SimpleDropDownPicker.vue';
import NButton from '@/components/basic/Button.vue';
import FlexCol from '@/components/layout/FlexCol.vue';
import Text from '@/components/basic/Text.vue';
import Icon from '@/components/basic/Icon.vue';
import ActivityIndicator from '@/components/basic/ActivityIndicator.vue';
import Dialog from '@/components/dialog/Dialog.vue';
import Field from '@/components/form/Field.vue';
import FlexRow from '@/components/layout/FlexRow.vue';
import StatusBarSpace from '@/components/layout/space/StatusBarSpace.vue';
import RegionApi from '@/api/map/RegionApi';
import type { MapMarker } from '@/types/Map';
import { hideLoading, loading } from '@/components/utils/DialogAction';
import { showError } from '@/common/composeabe/ErrorDisplay';
import FrameButton from '@/common/components/FrameButton.vue';
import BoxMid from '@/common/components/box/BoxMid.vue';
import Width from '@/components/layout/space/Width.vue';
import BackgroundBox from '@/components/display/block/BackgroundBox.vue';
import { navTo } from '@/components/utils/PageAction';

const instance = getCurrentInstance();
const mapCtx = uni.createMapContext('prevMap', instance);

const selectedRegion = ref<number>();
const villageData = new Map<number, VillageMapItem>();

const ready = ref(false);
const hasResItems = ref(false);

const emit = defineEmits([
  'getCurrentLonlat',
  'update:isLightMode', 
  'update:lonlat',
  'update:district',
  'selectVillage',
  'regionChanged',
  'lightVillage',
  'createVillage',
  'changeCity',
  'mapClick',
]);

const props = withDefaults(defineProps<{
  lonlat?: { longitude: number, latitude: number } | undefined;
  city?: string;
  cityCode?: number;
  district?: string;
  isLightMode?: boolean;
  small?: boolean;
  full?: boolean;
}>(), {
});


const lightState = ref(1);
const showLighted = computed(() => lightState.value === 2 || lightState.value === 1);
const showUnLighted = computed(() => lightState.value === 3 || lightState.value === 1);

const regionLoader = useSimpleDataLoader(async () => {
  if (!props.cityCode)
    return [];
  return ((await RegionApi.getChildList(props.cityCode))
    .filter(p => p.areaCode !== props.cityCode && p.name !== '市辖区')
    .map(p => ({
      ...p,
      name: p.name,
      id: p.areaCode,
    })));
}, false);
const mapLoader = useSimpleDataLoader<MapMarker[]>(async () => {
  mapCtx.removeMarkers({
    markerIds: Array.from(villageData.keys()),
  })
  villageData.clear();
  if (!selectedRegion.value)
    return [];
  await waitTimeOut(100);
  let res = (await LightVillageApi.getMapVillage({
    areaCode: selectedRegion.value
  }));

  //如果小地图则只显示200个
  if (props.small && res.length > 200)
    res.splice(200, res.length - 200);

  //如果为空则尝试获取子级
  hasResItems.value = res.length > 0;
  const list = res
    .filter(p => {
      if (p.isLight && showLighted.value)
        return true;
      if (!p.isLight && showUnLighted.value)
        return true;
      return false;
    })
    .map((p, i) => {
      const id = p.villageId ?? i;
      villageData.set(id, p);
      const maker : MapMarker = {
        id,
        title: p.name,
        longitude: Number(p.longitude),
        latitude: Number(p.latitude),
        width: 30,
        height: 30,
        iconPath: '',
        joinCluster: true,
        callout: {
          display: props.small ? 'BYCLICK' : 'ALWAYS',
          content: p.name,
          color: '#000000',
          fontSize: 12,
          padding: 5,
          bgColor: '#ffffff',
          borderRadius: 5,
        },
      }

      if (p.isLight && p.villageId) {
        if (p.lightValue >= 1) {
          maker.iconPath = `https://mncdn.wenlvti.net/app_static/xiangyuan/images/map/Light3.png`;
        } else if (p.lightValue >= 0.5) {
          maker.iconPath = `https://mncdn.wenlvti.net/app_static/xiangyuan/images/map/Light2.png`;
        } else if (p.lightValue >= 0.25) {
          maker.iconPath = `https://mncdn.wenlvti.net/app_static/xiangyuan/images/map/Light1.png`;
        } else {
          maker.iconPath = `https://mncdn.wenlvti.net/app_static/xiangyuan/images/map/Light1.png`;
        }
        const size = Math.floor(30 +(p.lightValue) * 40);
        maker.width = size;
        maker.height = Math.floor(size * 1.05);
        
      } else {
        maker.width = 25;
        maker.height = 27;
        maker.iconPath = `https://mncdn.wenlvti.net/app_static/xiangyuan/images/map/LightUnLight.png`;
      }
      return maker as MapMarker;
    })
    .filter(p => 
      p.longitude && p.latitude 
      && !isNaN(p.longitude) && !isNaN(p.latitude)
      && p.longitude > -180 && p.longitude < 180
      && p.latitude > -90 && p.latitude < 90
    );

  asyncAddMarkers(list);

  if (res.length == 1) {
    mapCtx.moveToLocation({
      latitude: Number(list[0].latitude),
      longitude: Number(list[0].longitude),
    });
  } else if (res.length > 1) {
    setTimeout(() => {
      mapCtx.includePoints({
        points: list.map(p => {
          if (!p.longitude || !p.latitude) {
            p.longitude = AppCofig.defaultLonLat[0];
            p.latitude = AppCofig.defaultLonLat[1];
          }
          return {
            latitude: p.latitude,
            longitude: p.longitude,
          }
        }),
        padding: [20, 20, 20, 20],
      });
    }, 200);
  } else {
    try {
      const currentRegion = regionLoader.content.value?.find(p => p.id == selectedRegion.value);
      if (currentRegion) {
        mapCtx.moveToLocation({
          latitude: Number(currentRegion.latitude),
          longitude: Number(currentRegion.longitude),
        });
      }
    } catch (error) {
      console.error(error);
    }
  }
  ready.value = true;
  return list;
}, false, false);

const BATCH_SIZE = 25;

async function asyncAddMarkers(list: MapMarker[]) {
  if (list.length <= BATCH_SIZE) {
    mapCtx.addMarkers({
      clear: true,
      markers: list,
    });
    return;
  }
  for (let i = 0; i < list.length; i += BATCH_SIZE) {
    const batch = list.slice(i, i + BATCH_SIZE);
    mapCtx.addMarkers({
      clear: i === 0,
      markers: batch,
    });
    if (i + BATCH_SIZE < list.length) {
      await waitTimeOut(300);
    }
  }
}

async function onMarkerTap(e: any) {
  try {
    loading();
    const villageMapInfo = villageData.get(e.markerId);
    assertNotNull(villageMapInfo, 'markerId错误');
    if (!villageMapInfo.villageId) {
      emit('createVillage', villageMapInfo);
      return;
    }
    const village = await LightVillageApi.getVillageDetails(villageMapInfo.villageId);
    assertNotNull(village, '获取村社详情失败');

    if (props.isLightMode) {
      emit('update:isLightMode', false);
      emit('lightVillage', village);
      return;
    }

    emit('selectVillage', village);
  } catch (error) {
    showError(error);
  } finally {
    hideLoading();
  }
}
function onSelectedRegion(regionId: number) {
  selectedRegion.value = regionId;
  mapLoader.reload();
  emit('update:district', regionLoader.content.value?.find(p => p.id === regionId)?.name);
  emit('regionChanged', regionId);
}
function setCurrentRegion(regionAreaCode: number) {
  if (regionAreaCode === selectedRegion.value)
    return;
  selectedRegion.value = regionAreaCode;
  emit('regionChanged', selectedRegion.value);
  mapLoader.reload();
}
function loadFirstRegion() {
  //加载第一个地区（排除市辖区)
  let code : number | undefined = undefined;
  if (props.district)
    code = regionLoader.content.value?.find((p) => p.name === props.district)?.areaCode;
  if (!code)
    code = regionLoader.content.value?.find((p) => p.id !== props.cityCode)?.areaCode;
  if (!code)
    code = regionLoader.content.value?.[0]?.areaCode;

  if (code)
    setCurrentRegion(code);
  console.log('加载区域数据', code, regionLoader.content.value, props.district);
}

function showSearch() {
  navTo('/pages/home/search/index');
} 

watch(() => props.cityCode, async () => {
  await regionLoader.reload();
  loadFirstRegion();
}, { immediate: true });
watch(showLighted, () => mapLoader.reload());
watch(showUnLighted, () => mapLoader.reload());

onMounted(async () => {
  mapCtx.initMarkerCluster({
    enableDefaultStyle: false,
    zoomOnClick: true,
    gridSize: props.small ? 25 : 50,
  });
  mapCtx.on('markerClusterCreate', (e: { clusters: any[] }) => {
    const customClusters = e.clusters.map((cluster) => {
      const { center, clusterId, markerIds } = cluster;
      return {
        ...center,
        width: 0,
        height: 0,
        clusterId,
        label: {
          content: markerIds.length.toString(), // 聚合点的数量
          fontSize: 16,
          color: '#fff',
          width: 30,
          height: 30,
          bgColor: '#8bb346', // 背景颜色
          borderRadius: 25,
          textAlign: 'center',
          anchorX: -10,
          anchorY: -35,
        },
      };
    });
    mapCtx.addMarkers({
      markers: customClusters,
      clear: false,
    });
  });
});

defineExpose({
  showSearch,
  reload: async () => {
    await regionLoader.reload();
    loadFirstRegion();
  },
});
</script>

<style lang="scss">
.light-map {
  position: relative;
  width: 100%;
  height: 600rpx;
  border-radius: 30rpx;
  overflow: hidden;
  border: 1px solid #d45652;

  &.full {
    height: 100vh;
    border-radius: 0;

    .light-map-map {
      height: 100vh;
    }
  }
  &.small {
    height: 400rpx;
    border-radius: 20rpx;
    .light-map-map {
      height: 400rpx;
    }
  }

  .light-map-map {
    width: 100%;
    height: 600rpx;
  }
  .light-map-address {
    position: absolute;
    bottom: 20rpx;
    right: 20rpx;
    z-index: 100;
  }
}
</style>