const storageAccessService = require('../storage-access/service.js')
const transport = require('../../transport/ble-core.js')
const {
  AREA
} = require('../../protocols/storage-access/index.js')
const {
  bytesToHex,
  stringToUtf8Bytes
} = require('../../utils/binary-utils.js')
const {
  STORAGE_ACCESS_AREA_OPTIONS,
  STORAGE_ACCESS_COMMAND_OPTIONS,
  normalizeSerialState,
  parseHexBytes,
  validateHexText
} = require('./view-model.js')

function getStorageAccessCommand(index) {
  return STORAGE_ACCESS_COMMAND_OPTIONS[Number(index) || 0] || STORAGE_ACCESS_COMMAND_OPTIONS[0]
}

function getStorageAccessArea(index) {
  return STORAGE_ACCESS_AREA_OPTIONS[Number(index) || 0] || STORAGE_ACCESS_AREA_OPTIONS[0]
}

async function sendSerialFrame(data = {}) {
  const serialInputText = String(data.serialInputText || '')
  const serialState = normalizeSerialState(data)
  const mode = serialState.serialMode

  if (!data.connectedDevice) {
    return {
      errorText: '请先连接蓝牙设备',
      ok: false
    }
  }

  if (serialState.serialErrorText) {
    return {
      errorText: serialState.serialErrorText,
      ok: false
    }
  }

  if (mode === 'hex') {
    const errorText = validateHexText(serialInputText)
    if (errorText) {
      return {
        errorText,
        ok: false
      }
    }

    const bytes = parseHexBytes(serialInputText)
    const previewHex = bytesToHex(bytes, ' ')
    const ok = await transport.sendRawFrameExact(new Uint8Array(bytes), 'SERIAL')

    return {
      bytes,
      ok,
      previewHex,
      serialState
    }
  }

  const bytes = stringToUtf8Bytes(serialInputText)
  if (!bytes.length) {
    return {
      errorText: '请输入要发送的文本',
      ok: false
    }
  }

  const ok = await transport.sendRawFrameExact(new Uint8Array(bytes), 'SERIAL')

  return {
    bytes,
    ok,
    previewHex: bytesToHex(bytes, ' '),
    serialState
  }
}

async function syncStorageAccessCodeInfo(data = {}) {
  const result = await storageAccessService.syncCodeInfo({
    maxPacketLength: data.parameterMaxPacketLength,
    showModal: true
  })

  if (!result || !result.ok) {
    return {
      ok: false
    }
  }

  const codeInfoAddressText = result.codeInfoAddressText || Number(result.codeInfoAddress || 0).toString(16).toUpperCase().padStart(4, '0')
  const codeInfoByteLengthText = result.codeInfoByteLengthText || Number(result.codeInfoByteLength || 0).toString(16).toUpperCase().padStart(4, '0')

  return {
    codeInfoAddress: result.codeInfoAddress,
    codeInfoAddressText,
    codeInfoByteLength: result.codeInfoByteLength,
    codeInfoByteLengthText,
    ok: true,
    syncInfoText: `0x0F info ${codeInfoAddressText}/${codeInfoByteLengthText}`
  }
}

async function executeStorageAccessProtocol(data = {}) {
  const command = getStorageAccessCommand(data.storageAccessCommandIndex)
  const area = getStorageAccessArea(data.storageAccessAreaIndex)
  const address = parseInt(data.storageAccessAddress || '0000', 16) || 0
  const length = parseInt(data.storageAccessLength || '0004', 16) || 0
  const dataBytes = parseHexBytes(data.storageAccessDataText || '')

  if (!data.connectedDevice) {
    return {
      errorText: '请先连接蓝牙设备',
      ok: false
    }
  }

  if (data.storageAccessErrorText) {
    return {
      errorText: data.storageAccessErrorText,
      ok: false
    }
  }

  if (command.key === 'sync') {
    return syncStorageAccessCodeInfo(data)
  }

  if (command.key === 'write' && (area.key === AREA.CODE || area.key === AREA.INFO)) {
    return {
      errorText: 'code/info 区暂不支持写入',
      ok: false
    }
  }

  if (command.key === 'read') {
    const bytes = await storageAccessService.readMemory(
      area.key,
      address,
      length,
      '私有协议读取',
      'communication-storage-read',
      {
        maxPacketLength: data.parameterMaxPacketLength,
        showModal: true
      }
    )

    return {
      bytes,
      ok: !!bytes,
      previewHex: bytes ? bytesToHex(bytes, ' ') : ''
    }
  }

  const errorText = validateHexText(data.storageAccessDataText)
  if (errorText) {
    return {
      errorText,
      ok: false
    }
  }

  if (dataBytes.length !== length) {
    return {
      errorText: `写入长度为 ${length} 字节，当前数据为 ${dataBytes.length} 字节`,
      ok: false
    }
  }

  const ok = await storageAccessService.writeMemory(
    area.key,
    address,
    dataBytes,
    '私有协议写入',
    'communication-storage-write',
    {
      maxPacketLength: data.parameterMaxPacketLength,
      showModal: true
    }
  )

  return {
    ok
  }
}

module.exports = {
  executeStorageAccessProtocol,
  sendSerialFrame
}
