import type { NetworkConfig, NetworkInstance, NetworkInstanceRunningInfo } from '~/types/network'
import { DEFAULT_NETWORK_CONFIG } from '~/types/network'

export const useNetworkStore = defineStore('networkStore', {
  state: () => {
    const networkList = [DEFAULT_NETWORK_CONFIG()]
    return {
      // for initially empty lists
      networkList: networkList as NetworkConfig[],
      // for data that is not yet loaded
      curNetwork: networkList[0],

      // uuid -> instance
      instances: {} as Record<string, NetworkInstance>,

      networkInfos: {} as Record<string, NetworkInstanceRunningInfo>,
    }
  },

  getters: {
    lastNetwork(): NetworkConfig {
      return this.networkList[this.networkList.length - 1]
    },

    curNetworkId(): string {
      return this.curNetwork.instance_id
    },

    networkInstances(): Array<NetworkInstance> {
      return Object.values(this.instances)
    },

    networkInstanceIds(): Array<string> {
      return Object.keys(this.instances)
    },
  },

  actions: {
    addNewNetwork() {
      this.networkList.push(DEFAULT_NETWORK_CONFIG())
    },

    delCurNetwork() {
      const curNetworkIdx = this.networkList.indexOf(this.curNetwork)
      this.networkList.splice(curNetworkIdx, 1)
      const nextCurNetworkIdx = Math.min(curNetworkIdx, this.networkList.length - 1)
      this.curNetwork = this.networkList[nextCurNetworkIdx]
    },

    removeNetworkInstance(instanceId: string) {
      delete this.instances[instanceId]
    },

    addNetworkInstance(instanceId: string) {
      this.instances[instanceId] = {
        instance_id: instanceId,
        running: false,
        error_msg: '',
        detail: undefined,
      }
    },

    updateWithNetworkInfos(networkInfos: Record<string, NetworkInstanceRunningInfo>) {
      this.networkInfos = networkInfos
      for (const [instanceId, info] of Object.entries(networkInfos)) {
        if (this.instances[instanceId] === undefined)
          this.addNetworkInstance(instanceId)

        this.instances[instanceId].running = info.running
        this.instances[instanceId].error_msg = info.error_msg || ''
        this.instances[instanceId].detail = info
      }
      this.saveRunningInstanceIdsToLocalStorage()
    },

    loadFromLocalStorage() {
      let networkList: NetworkConfig[]

      // if localStorage default is [{}], instanceId will be undefined
      networkList = JSON.parse(localStorage.getItem('networkList') || '[]')
      networkList = networkList.map((cfg) => {
        return { ...DEFAULT_NETWORK_CONFIG(), ...cfg } as NetworkConfig
      })

      // prevent a empty list from localStorage, should not happen
      if (networkList.length === 0)
        networkList = [DEFAULT_NETWORK_CONFIG()]

      this.networkList = networkList
      this.curNetwork = this.networkList[0]
    },

    saveToLocalStorage() {
      localStorage.setItem('networkList', JSON.stringify(this.networkList))
    },

    saveRunningInstanceIdsToLocalStorage() {
      let instance_ids = Object.keys(this.instances).filter((instanceId) => this.instances[instanceId].running)
      localStorage.setItem('runningInstanceIds', JSON.stringify(instance_ids))
    }
  },
})

if (import.meta.hot)
  import.meta.hot.accept(acceptHMRUpdate(useNetworkStore as any, import.meta.hot))

export function loadRunningInstanceIdsFromLocalStorage(): string[] {
  try {
    return JSON.parse(localStorage.getItem('runningInstanceIds') || '[]')
  } catch (e) {
    console.error(e)
    return []
  }
}
