import { InjectionKey } from 'vue'
import { ActionTree, createStore, GetterTree, MutationTree, Store, StoreOptions, useStore } from 'vuex'
import { EDeviceTypeName } from '../types'
import { Device, DeviceHms, DeviceOsd, DeviceStatus, DockOsd, GatewayOsd, OSDVisible } from '../types/device'
import { getLayers } from '/@/api/layer'
import { LayerType } from '/@/types/mapLayer'
import { WaylineFile } from '/@/types/wayline'
import { DevicesCmdExecuteInfo } from '/@/types/device-cmd'

const initStateFunc = () => ({
  trajectoryList: [],// 轨迹列表
  realTimeTrajectory: {// 实时轨迹
    sn: '',
    host: []
  },
  deviceReason: {} as {
    [sn: string]: any,
  },
  dockTask: {} as {
    [sn: string]: any,
  },
  mapClickElement: {
    id: '',
    type: '',
  },
  Layers: [
    // {
    //   name: '默认',
    //   id: '',
    //   is_distributed: true,
    //   elements: [],
    //   is_check: false,
    //   is_select: false,
    //   type: 1
    // },
    // {
    //   name: '分享',
    //   id: '',
    //   is_distributed: true,
    //   elements: [],
    //   is_check: false,
    //   is_select: false,
    //   type: 2
    // }
  ],
  layerBaseInfo: {} as {
    [key: string]: string
  },
  livestreamOthersVisible: false,
  livestreamAgoraVisible: false,
  coverMap: {} as {
    [key: string]: any[]
  },
  wsEvent: {
    mapElementCreat: {},
    mapElementUpdate: {},
    mapElementDelete: {}
  },
  deviceStatusEvent: {
    deviceOnline: {} as DeviceStatus,
    deviceOffline: {}
  },
  markerInfo: {
    coverMap: {} as {
      [sn: string]: any
    },
    pathMap: {} as {
      [sn: string]: any[]
    }
  },
  deviceState: {
    // remote controller, dock
    gatewayInfo: {} as {
      [sn: string]: GatewayOsd
    },
    // drone
    deviceInfo: {} as {
      [sn: string]: DeviceOsd
    },
    dockInfo: {} as {
      [sn: string]: DockOsd
    },
    currentSn: '',
    currentType: -1
  },
  osdVisible: { // osd 显示设备相关信息
    sn: '',
    callsign: '',
    model: '',
    visible: false,
    gateway_sn: '',
    is_dock: false,
    payloads: null
  } as OSDVisible,
  waylineInfo: {

  } as WaylineFile,
  dockInfo: {

  } as Device,
  hmsInfo: {} as {
    [sn: string]: DeviceHms[]
  },
  // 机场指令执行状态信息
  devicesCmdExecuteInfo: {
  } as DevicesCmdExecuteInfo,
  mqttState: null as any, // mqtt 实例
  clientId: '', // mqtt 连接 唯一客户端id
})

export type RootStateType = ReturnType<typeof initStateFunc>

const getters: GetterTree<RootStateType, RootStateType> = {
}
const mutations: MutationTree<RootStateType> = {
  SET_TRAJECTORY_LIST(state, list) {
    state.trajectoryList = list
  },
  SET_REAL_TIME_TRAJECTORY(state, info) {
    state.realTimeTrajectory = info
  },
  SET_DEVICE_REASON(state, info) {
    state.deviceReason[info.sn] = info
  },
  SET_DOCK_TASK(state, info) {
    state.dockTask[info.sn] = {
      name: info.output.ext.job_name,
    }
  },
  SET_MAP_CLICK_ELEMENT(state, info) {
    state.mapClickElement = info
  },
  SET_LAYER_INFO(state, info) {
    state.Layers = info
  },
  SET_DEVICE_INFO(state, info) {
    state.deviceState.deviceInfo[info.sn] = info.host
    state.deviceState.currentSn = info.sn
    state.deviceState.currentType = EDeviceTypeName.Aircraft
  },
  SET_GATEWAY_INFO(state, info) {
    state.deviceState.gatewayInfo[info.sn] = info.host
    state.deviceState.currentSn = info.sn
    state.deviceState.currentType = EDeviceTypeName.Gateway
  },
  SET_DOCK_INFO(state, info) {
    if (Object.keys(info.host).length === 0) {
      return
    }
    if (!state.deviceState.dockInfo[info.sn]) {
      state.deviceState.dockInfo[info.sn] = {} as DockOsd
    }
    state.deviceState.currentSn = info.sn
    state.deviceState.currentType = EDeviceTypeName.Dock
    const dock = state.deviceState.dockInfo[info.sn]
    if (info.host.mode_code !== undefined) {
      dock.basic_osd = info.host
      return
    }
    if (info.host.wireless_link) {
      dock.link_osd = info.host
      return
    }
    if (info.host.job_number !== undefined) {
      dock.work_osd = info.host
    }
  },
  SET_LIVESTREAM_OTHERS_VISIBLE(state, bool) {
    state.livestreamOthersVisible = bool
  },
  SET_LIVESTREAM_AGORA_VISIBLE(state, bool) {
    state.livestreamAgoraVisible = bool
  },
  SET_MAP_ELEMENT_CREATE(state, info) {
    state.wsEvent.mapElementCreat = info
  },
  SET_MAP_ELEMENT_UPDATE(state, info) {
    state.wsEvent.mapElementUpdate = info
  },
  SET_MAP_ELEMENT_DELETE(state, info) {
    state.wsEvent.mapElementDelete = info
  },
  SET_DEVICE_ONLINE(state, info) {
    state.deviceStatusEvent.deviceOnline = info
  },
  SET_DEVICE_OFFLINE(state, info) {
    state.deviceStatusEvent.deviceOffline = info
    delete state.deviceState.gatewayInfo[info.sn]
    delete state.deviceState.deviceInfo[info.sn]
    delete state.deviceState.dockInfo[info.sn]
    delete state.hmsInfo[info.sn]
    // delete state.markerInfo.coverMap[info.sn]
    // delete state.markerInfo.pathMap[info.sn]
  },
  SET_OSD_VISIBLE_INFO(state, info) {
    state.osdVisible = info
  },
  SET_SELECT_WAYLINE_INFO(state, info) {
    state.waylineInfo = info
  },
  SET_SELECT_DOCK_INFO(state, info) {
    state.dockInfo = info
  },
  SET_DEVICE_HMS_INFO(state, info) {
    const hmsList: Array<DeviceHms> = state.hmsInfo[info.sn]
    state.hmsInfo[info.sn] = info.host.concat(hmsList ?? [])
  },
  SET_DEVICES_CMD_EXECUTE_INFO(state, info) { // 保存设备指令ws消息推送
    if (!info.sn) {
      return
    }
    if (state.devicesCmdExecuteInfo[info.sn]) {
      const index = state.devicesCmdExecuteInfo[info.sn].findIndex(cmdExecuteInfo => cmdExecuteInfo.biz_code === info.biz_code)
      if (index >= 0) {
        // 丢弃前面的消息
        if (state.devicesCmdExecuteInfo[info.sn][index].timestamp > info.timestamp) {
          return
        }
        state.devicesCmdExecuteInfo[info.sn][index] = info
      } else {
        state.devicesCmdExecuteInfo[info.sn].push(info)
      }
    } else {
      state.devicesCmdExecuteInfo[info.sn] = [info]
    }
  },
  SET_MQTT_STATE(state, mqttState) {
    state.mqttState = mqttState
  },
  SET_CLIENT_ID(state, clientId) {
    state.clientId = clientId
  },
}

const actions: ActionTree<RootStateType, RootStateType> = {
  async getAllElement({ commit }) {
    const result = await getLayers({
      groupId: '',
      isDistributed: true
    })
    commit('SET_LAYER_INFO', result.data?.list)
  },
  updateElement({ state }, content: { type: 'is_check' | 'is_select', id: string, bool: boolean }) {
    const key = content.id.replaceAll('resource__', '')
    const type = content.type
    const layers = state.Layers
    const layer = layers.find(item => item.id === key)
    if (layer) {
      layer[type] = content.bool
    }
  },
  setLayerInfo({ state }, layers) {
    // const layers = state.Layers
    const obj: {
      [key: string]: string
    } = {}
    layers.forEach(layer => {
      if (layer.type === LayerType.Default) {
        obj.default = layer.id
      } else {
        if (layer.type === LayerType.Share) {
          obj.share = layer.id
        }
      }
    })
    state.layerBaseInfo = obj
  },
  getLayerInfo({ state }, id: string) {
    return state.layerBaseInfo[id]
  }
}

const storeOptions: StoreOptions<RootStateType> = {
  state: initStateFunc,
  getters,
  mutations,
  actions
}

const rootStore = createStore(storeOptions)

export default rootStore

export const storeKey: InjectionKey<Store<RootStateType>> = Symbol('')

type AllStateStoreTypes = RootStateType & {
  // moduleName: moduleType
}

export function useMyStore<T = AllStateStoreTypes>() {
  return useStore<T>(storeKey)
}