const SCALE_MAX = 32767
const ATT_COEF = 0.85
const TWO_PI = 2 * 3.1415926

const DEFAULT_DRIVER_PARAMS = {
  carrierFrequencyKHz: 16,
  baseVoltage: 5.0,
  opAmpGain: 4,
  samplingResistorMohm: 100,
  busVoltageDividerRatio: 996.8 / 6.8,
  analogInputDividerRatio: 200 / 268
}

let currentDriverParams = {
  ...DEFAULT_DRIVER_PARAMS
}

const sharedInputValues = {}

const FAULT_CODE_MAP = {
  0x01: '硬件过流',
  0x02: '软件过流',
  0x03: '风扇过流',
  0x04: '电流偏置校准失败',
  0x05: '缺相',
  0x06: '驱动器上桥短路',
  0x07: '驱动器下桥短路',
  0x08: '相间短路',
  0x09: '启动堵转',
  0x0A: '运行堵转',
  0x0B: '过功率',
  0x0C: '过压',
  0x0D: '欠压',
  0x0E: '芯片欠压',
  0x0F: 'NTC过温',
  0x10: '电机过温',
  0x11: 'IPM过温',
  0x12: '芯片过温',
  0x13: '串口丢失',
  0x14: 'PWM丢失'
}

function toFiniteNumber(value, fallback = 0) {
  if (typeof value === 'string') {
    const text = value.trim()
    const directValue = Number(text)
    if (Number.isFinite(directValue)) return directValue

    const match = text.match(/^[+-]?(?:\d+\.?\d*|\.\d+)(?:e[+-]?\d+)?/i)
    const textValue = match ? Number(match[0]) : NaN

    return Number.isFinite(textValue) ? textValue : fallback
  }

  const numberValue = Number(value)

  return Number.isFinite(numberValue) ? numberValue : fallback
}

function getSharedInputValues() {
  return {
    ...sharedInputValues
  }
}

function getDriverParams() {
  return {
    ...currentDriverParams
  }
}

function updateDriverParams(params = {}) {
  currentDriverParams = {
    ...currentDriverParams,
    ...Object.keys(params).reduce((result, key) => {
      const value = toFiniteNumber(params[key], NaN)
      if (Number.isFinite(value) && value > 0) {
        result[key] = value
      }
      return result
    }, {})
  }
}

function getSharedInputDefault() {
  return 0
}

function setSharedInputValue(name, value, fallback = getSharedInputDefault(name)) {
  sharedInputValues[name] = toFiniteNumber(value, fallback)
}

function setSharedInputValues(registers) {
  registers.forEach((item) => {
    setSharedInputValue(item.name, item.inputValue, getSharedInputDefault(item.name))
  })
}

function mergeInputValues(registers = []) {
  return registers.reduce((result, item) => {
    const fallback = Object.prototype.hasOwnProperty.call(result, item.name) ? result[item.name] : getSharedInputDefault(item.name)
    result[item.name] = toFiniteNumber(item.inputValue, fallback)
    return result
  }, getSharedInputValues())
}

function getFaultText(code) {
  const numberValue = Number(code)
  if (!Number.isFinite(numberValue) || numberValue === 0) return '无故障'

  return FAULT_CODE_MAP[numberValue] || '未知故障'
}

module.exports = {
  ATT_COEF,
  DEFAULT_DRIVER_PARAMS,
  SCALE_MAX,
  TWO_PI,
  getFaultText,
  getDriverParams,
  getSharedInputValues,
  getSharedInputDefault,
  mergeInputValues,
  setSharedInputValues,
  updateDriverParams,
  toFiniteNumber
}
