const transport = require('../../transport/ble-core.js')
const manualRtuService = require('../manual-rtu/service.js')
const themeService = require('../../store/theme-store.js')
const {
  DEFAULT_DEVICE_FILTER,
  getHomePageState
} = require('./view-model.js')

let syncService = null
let initScheduled = false
const syncSubscriptionHooks = []

function deferStartupWork(task) {
  if (typeof task !== 'function') return

  if (typeof setTimeout === 'function') {
    setTimeout(task, 120)
    return
  }

  task()
}

function getSyncService() {
  if (!syncService) {
    syncService = require('../motor-control/sync-service.js')
    syncSubscriptionHooks.slice().forEach((hook) => {
      hook(syncService)
    })
  }

  return syncService
}

function getSyncState() {
  return syncService ? syncService.getState() : {
    isSyncing: false
  }
}

function init() {
  if (initScheduled) return

  initScheduled = true
  deferStartupWork(() => {
    try {
      themeService.init()
    } catch (error) {}
  })
}

function getState(deviceFilterMode = DEFAULT_DEVICE_FILTER) {
  return getHomePageState(
    transport.getState(),
    deviceFilterMode,
    getSyncState(),
    themeService.getState(),
    manualRtuService.getState()
  )
}

function subscribeState(getDeviceFilterMode, subscriber) {
  if (typeof subscriber !== 'function') return () => {}

  const getFilterMode = typeof getDeviceFilterMode === 'function'
    ? getDeviceFilterMode
    : () => DEFAULT_DEVICE_FILTER
  const emit = () => subscriber(getState(getFilterMode()))
  let syncUnsubscribe = null
  const syncHook = (service) => {
    if (!syncUnsubscribe) {
      syncUnsubscribe = service.subscribe(emit)
    }
  }

  syncSubscriptionHooks.push(syncHook)
  if (syncService) syncHook(syncService)

  const unsubscribers = [
    transport.subscribe(emit),
    manualRtuService.subscribe(emit),
    themeService.subscribe(emit)
  ]

  return () => {
    unsubscribers.forEach((unsubscribe) => {
      if (typeof unsubscribe === 'function') unsubscribe()
    })

    if (typeof syncUnsubscribe === 'function') syncUnsubscribe()

    const index = syncSubscriptionHooks.indexOf(syncHook)
    if (index >= 0) syncSubscriptionHooks.splice(index, 1)
  }
}

function toggleScan(isDiscovering) {
  return isDiscovering ? transport.stopScan() : transport.startScan()
}

module.exports = {
  DEFAULT_DEVICE_FILTER,
  clearDevices: transport.clearDevices,
  clearInput: transport.clearInput,
  clearLogs: transport.clearLogs,
  closeProtocolMultipleDialog: manualRtuService.closeProtocolMultipleDialog,
  connectDeviceById: transport.connectDeviceById,
  disconnectDevice: transport.disconnectDevice,
  getState,
  init,
  openProtocolMultipleDialog: manualRtuService.openProtocolMultipleDialog,
  sendGeneratedFrame: manualRtuService.sendGeneratedFrame,
  sendHexFrame: transport.sendHexFrame,
  setCommandIndex: manualRtuService.setCommandIndex,
  setProtocolInput: manualRtuService.setProtocolInput,
  setProtocolMultipleQuantity: manualRtuService.setProtocolMultipleQuantity,
  setProtocolMultipleTextLength: manualRtuService.setProtocolMultipleTextLength,
  setProtocolMultipleType: manualRtuService.setProtocolMultipleType,
  setProtocolMultipleValue: manualRtuService.setProtocolMultipleValue,
  setSendHex: transport.setSendHex,
  subscribeState,
  syncRegisters: () => getSyncService().syncAllRegisters(),
  toggleScan,
  validateProtocolMultipleValue: manualRtuService.validateProtocolMultipleValue
}
