const {
  parseHexInteger
} = require('./base-utils')
const {
  getRegisterCount
} = require('./registers')

function parseRegisterAddress(address) {
  return parseHexInteger(address)
}

function getAreaKey(item) {
  return (item.area && item.area.key) || item.areaKey || 'holding'
}

function getGroupItems(data, groupKey) {
  if (groupKey === 'vsp') return data.vspCurveRegisters.concat([data.speedSlopeRegister])
  if (groupKey === 'speedLoop') {
    return data.speedLoopInputDisplayRegisters
      .concat(data.speedLoopExtraDisplayRegisters)
  }
  if (groupKey === 'estimator') {
    return data.estimatorCalculatedDisplayRegisters.concat(data.atoBandwidthDisplayRegisters)
  }
  if (groupKey === 'tailwind') {
    return data.tailwindControlRegisters
      .concat(data.tailwindCalculatedDisplayRegisters, data.tailwindAtoBandwidthDisplayRegisters)
  }
  if (groupKey === 'preposition') return data.prepositionSwitchRegisters.concat(data.prepositionParameterDisplayRegisters)
  if (groupKey === 'oil') return data.oilParameterInputRegisters
  if (groupKey === 'dq') return data.dqGainDisplayRegisters
  if (groupKey === 'protection') return data.protectionSwitchRegisters.concat(data.protectionDisplayRegisters)

  return []
}

function expandAtoItems(item) {
  if (!item.kpAddress || !item.kiAddress) return [item]

  return [
    {
      address: item.kpAddress,
      areaKey: 'holding',
      name: `${item.name} KP`,
      type: 'uint16_t',
      writeValue: item.kpWriteValue
    },
    {
      address: item.kiAddress,
      areaKey: 'holding',
      name: `${item.name} KI`,
      type: 'uint16_t',
      writeValue: item.kiWriteValue
    }
  ]
}

function expandItems(items) {
  return items.reduce((result, item) => result.concat(expandAtoItems(item)), [])
}

function makeReadSpans(entries) {
  const sortedEntries = entries
    .map((item) => ({
      address: parseRegisterAddress(item.address),
      count: getRegisterCount(item)
    }))
    .filter((item) => Number.isFinite(item.address) && item.count > 0)
    .sort((left, right) => left.address - right.address)
  const spans = []

  sortedEntries.forEach((entry) => {
    const last = spans[spans.length - 1]

    if (last && entry.address <= last.address + last.quantity) {
      const end = Math.max(last.address + last.quantity, entry.address + entry.count)
      last.quantity = end - last.address
      return
    }

    spans.push({
      address: entry.address,
      quantity: entry.count
    })
  })

  return spans
}

function mergeReadValues(target, source) {
  if (!target || !source) return

  Object.assign(target.coils, source.coils || {})
  Object.assign(target.words, source.words || {})
}

module.exports = {
  expandItems,
  getAreaKey,
  getGroupItems,
  makeReadSpans,
  mergeReadValues,
  parseRegisterAddress
}
