const {
  formatBytes
} = require('../../utils/binary-utils.js')

const FILE_SIZES = {
  16: 16 * 1024,
  32: 32 * 1024
}
const FLASH_LAYOUTS = {
  16: {
    capacity: FILE_SIZES[16],
    startAddress: 0x0400,
    endAddress: 0x4000
  },
  32: {
    capacity: FILE_SIZES[32],
    startAddress: 0x0800,
    endAddress: 0x8000
  }
}
const FLASH_SIZE_TEXT = Object.keys(FILE_SIZES)
  .map((sizeKb) => formatBytes(FILE_SIZES[sizeKb]))
  .join(' 或 ')
const CHIP_FLASH_SIZE_KB = {
  FU6572L: 32,
  FU6572N: 32,
  FU6572T: 32,
  FU6565N: 32,
  FU6565T: 32,
  FU6563N: 32,
  FU6562L: 32,
  FU6562LA: 32,
  FU6562Q: 32,
  FU6562S: 32,
  FU6562T: 32,
  FU6532N: 32,
  FU6532T: 32,
  FU6522L: 32,
  FU6522N: 32,
  FU6522T: 32,
  FU6812L2: 16,
  FU6812N2: 16,
  FU6812S2: 16,
  FU6812V: 16,
  FU6861Q2: 16,
  FU6861N2: 16,
  FU6861NF2: 16,
  FU6861L2: 16,
  FU6862L: 16,
  FU6862Q: 16,
  FU6872P: 16
}
const CHIP_FAMILY_FLASH_SIZE_KB = {
  65: 32,
  68: 16
}

function normalizeModel(value) {
  const text = String(value || '').trim()
  return text && text !== '--' ? text : ''
}

function extractChipModels(chipModel) {
  const model = normalizeModel(chipModel).toUpperCase()
  return model.match(/FU\d{4}[A-Z0-9]*/g) || []
}

function inferFlashSizeKb(chipModel) {
  const models = extractChipModels(chipModel)

  for (const model of models) {
    if (CHIP_FLASH_SIZE_KB[model]) return CHIP_FLASH_SIZE_KB[model]

    const family = model.slice(2, 4)
    if (CHIP_FAMILY_FLASH_SIZE_KB[family]) return CHIP_FAMILY_FLASH_SIZE_KB[family]
  }

  const text = normalizeModel(chipModel).toUpperCase()
  if (/(^|[^0-9])32\s*K(B)?([^0-9]|$)/.test(text)) return 32
  if (/(^|[^0-9])16\s*K(B)?([^0-9]|$)/.test(text)) return 16

  return null
}

function inferFlashSizeKbFromBytes(byteLength) {
  return Number(Object.keys(FILE_SIZES).find((sizeKb) => FILE_SIZES[sizeKb] === byteLength)) || null
}

function inferUpgradeFlashSizeKb(chipModel, byteLength) {
  return inferFlashSizeKb(chipModel) || inferFlashSizeKbFromBytes(byteLength)
}

function getFlashLayout(chipModel, byteLength) {
  const sizeKb = inferUpgradeFlashSizeKb(chipModel, byteLength)
  return sizeKb ? FLASH_LAYOUTS[sizeKb] : null
}

function getFirmwareValidation(byteLength, chipModel) {
  const chipSizeKb = inferFlashSizeKb(chipModel)
  const firmwareSizeKb = inferFlashSizeKbFromBytes(byteLength)
  const sizeKb = chipSizeKb || firmwareSizeKb
  const layout = sizeKb ? FLASH_LAYOUTS[sizeKb] : null
  const normalizedChipModel = normalizeModel(chipModel)

  if (!byteLength) {
    return {
      isReady: false,
      text: chipSizeKb
        ? `需要 ${formatBytes(FLASH_LAYOUTS[chipSizeKb].capacity)} .bin`
        : `请选择 ${FLASH_SIZE_TEXT} .bin`
    }
  }

  if (!layout) {
    return {
      isReady: false,
      text: `文件 ${formatBytes(byteLength)}，应为 ${FLASH_SIZE_TEXT}`
    }
  }

  if (byteLength !== layout.capacity) {
    return {
      isReady: false,
      text: `文件 ${formatBytes(byteLength)}，应为 ${formatBytes(layout.capacity)}`
    }
  }

  return {
    isReady: true,
    text: chipSizeKb
      ? `匹配 ${formatBytes(layout.capacity)}`
      : `${normalizedChipModel ? `${normalizedChipModel} 未识别，` : '未读到芯片型号，'}按 ${formatBytes(layout.capacity)} 尝试`
  }
}

module.exports = {
  CHIP_FAMILY_FLASH_SIZE_KB,
  CHIP_FLASH_SIZE_KB,
  FILE_SIZES,
  FLASH_LAYOUTS,
  FLASH_SIZE_TEXT,
  extractChipModels,
  getFirmwareValidation,
  getFlashLayout,
  inferFlashSizeKb,
  inferFlashSizeKbFromBytes,
  inferUpgradeFlashSizeKb,
  normalizeModel
}
