const genericModbusService = require('./service.js')

const POLL_TIMER_ID = '__genericPoll'

function shouldPoll(data) {
  return !!data
    && (data.activeParamView === 'genericModbus' || data.activeParamView === 'genericModbusGroup')
    && !!data.connectedDevice
    && !!data.genericModbusAutoPollEnabled
}

function getPollableGroups(data) {
  return (data.genericModbusGroups || []).filter((group) => group.isReadOnly && !group.addressOverflow)
}

function createGenericModbusPoller(getData) {
  const timers = {}

  function clearTimer(timerId) {
    if (!timers[timerId]) return

    clearTimeout(timers[timerId])
    delete timers[timerId]
  }

  function clearAll() {
    Object.keys(timers).forEach(clearTimer)
  }

  function schedule(delay) {
    clearTimer(POLL_TIMER_ID)
    timers[POLL_TIMER_ID] = setTimeout(async () => {
      const data = getData()
      if (!shouldPoll(data)) {
        clearTimer(POLL_TIMER_ID)
        return
      }

      for (const group of getPollableGroups(data)) {
        const latestData = getData()
        if (!shouldPoll(latestData)) break

        await genericModbusService.readGroup(group.id, {
          maxPacketLength: latestData.genericModbusMaxPacketLength,
          showModal: false
        })
      }

      const latestData = getData()
      if (shouldPoll(latestData)) {
        schedule(latestData.genericModbusPollInterval || 100)
      }
    }, delay)
  }

  function scheduleVisible() {
    const data = getData()
    if (!shouldPoll(data)) {
      clearAll()
      return
    }

    schedule(data.genericModbusPollInterval || 100)
  }

  return {
    clearAll,
    clearTimer,
    schedule,
    scheduleVisible
  }
}

module.exports = {
  createGenericModbusPoller
}
