const {
  crcTool
} = require('../../tools/crc-hash/index.js')
const filterCalculator = require('../../tools/filter/index.js')
const smdCodeCalculator = require('../../tools/smd-code/index.js')
const refrigerationCalculator = require('../../tools/refrigeration/index.js')
const reactanceCalculator = require('../../tools/reactance/index.js')
const threePhasePowerCalculator = require('../../tools/three-phase-power/index.js')
const {
  getWxApi
} = require('../../utils/platform-utils.js')
const {
  loadSelectedFile
} = require('../../repositories/file.js')

function createToolInitialState() {
  return {
    ...crcTool.createInitialState(),
    ...filterCalculator.createInitialState(),
    ...smdCodeCalculator.createInitialState(),
    ...refrigerationCalculator.createInitialState(),
    ...reactanceCalculator.createInitialState(),
    ...threePhasePowerCalculator.createInitialState()
  }
}

const toolPageHandlers = {
  copyToolResult(event) {
    const value = event && event.currentTarget && event.currentTarget.dataset
      ? event.currentTarget.dataset.value
      : ''
    const text = String(value === undefined || value === null ? '' : value).trim()

    if (!text || text === '--') return

    const wxApi = getWxApi()
    if (typeof wxApi.setClipboardData !== 'function') {
      if (this.pageToast) this.pageToast.show('当前环境不支持复制', 'error')
      return
    }

    wxApi.setClipboardData({
      data: text,
      fail: () => {
        if (this.pageToast) this.pageToast.show('复制失败', 'error')
      },
      success: () => {
        if (this.pageToast) this.pageToast.show('已复制')
      }
    })
  },

  onCrcPresetChange(event) {
    const presetIndex = Number(event.detail.value)

    this.setData({
      ...crcTool.createPresetState(presetIndex),
      crcErrorText: ''
    })
  },

  onCrcInputTypeChange(event) {
    this.setData({
      crcErrorText: '',
      crcInputTypeIndex: Number(event.detail.value)
    })
  },

  onCrcConfigInput(event) {
    const field = event.currentTarget.dataset.field
    if (!field) return
    const isCrcConfigField = crcTool.CRC_CONFIG_FIELDS.includes(field)
    const nextData = {
      [field]: event.detail.value,
      crcErrorText: ''
    }

    if (isCrcConfigField) {
      nextData.crcAlgorithmCollapsed = false
      nextData.crcPresetIndex = crcTool.getCustomPresetIndex()
    }

    this.setData(nextData)
  },

  onCrcReflectChange(event) {
    const field = event.currentTarget.dataset.field
    if (!field) return

    this.setData({
      [field]: !!event.detail.value,
      crcAlgorithmCollapsed: false,
      crcErrorText: '',
      crcPresetIndex: crcTool.getCustomPresetIndex()
    })
  },

  toggleCrcAlgorithmPanel() {
    this.setData({
      crcAlgorithmCollapsed: !this.data.crcAlgorithmCollapsed
    })
  },

  onCrcDataInput(event) {
    this.crcFileBytes = null
    this.setData({
      crcDataText: event.detail.value,
      crcErrorText: '',
      crcFileName: '',
      crcFileSizeText: ''
    })
  },

  calculateCrc() {
    try {
      this.setData(crcTool.calculateFromState(this.data, this.crcFileBytes))
    } catch (error) {
      const message = error && error.message ? error.message : '计算失败'
      this.setData({
        crcErrorText: message
      })
      if (this.pageToast) this.pageToast.show(message, 'error')
    }
  },

  async loadCrcFileFromMessage() {
    try {
      const file = await loadSelectedFile('message')
      this.crcFileBytes = file.bytes
      this.setData({
        crcDataLengthText: file.sizeText,
        crcDataText: '',
        crcErrorText: '',
        crcFileName: file.name,
        crcFileSizeText: file.sizeText
      })
      this.calculateCrc()
    } catch (error) {
      const message = error && (error.errMsg || error.message)
        ? (error.errMsg || error.message)
        : '读取文件失败'

      if (!/cancel/i.test(message) && this.pageToast) {
        this.pageToast.show(message, 'error')
      }
    }
  },

  clearCrcInput() {
    this.crcFileBytes = null
    this.setData({
      crcDataLengthText: '0 bytes',
      crcDataText: '',
      crcErrorText: '',
      crcFileName: '',
      crcFileSizeText: '',
      crcResultBase64: '--',
      crcResultBin: '--',
      crcResultBinLines: [
        {
          id: 'bin-line-0',
          text: '--'
        }
      ],
      crcResultHex: '--'
    })
  },

  setFilterState(changedData) {
    this.setData(filterCalculator.updateState(this.data, changedData))
  },

  toggleFilterNetwork() {
    this.setFilterState({
      filterNetworkIndex: this.data.filterNetworkKey === 'rl' ? 0 : 1
    })
  },

  toggleFilterResponse() {
    this.setFilterState({
      filterResponseIndex: this.data.filterResponseKey === 'highpass' ? 0 : 1
    })
  },

  onFilterNetworkChange(event) {
    this.setFilterState({
      filterNetworkIndex: Number(event.detail.value)
    })
  },

  onFilterResponseChange(event) {
    this.setFilterState({
      filterResponseIndex: Number(event.detail.value)
    })
  },

  onFilterResistanceInput(event) {
    this.setFilterState({
      filterResistanceValue: event.detail.value
    })
  },

  onFilterReactiveInput(event) {
    this.setFilterState({
      filterReactiveValue: event.detail.value
    })
  },

  onFilterFrequencyInput(event) {
    this.setFilterState({
      filterFrequencyValue: event.detail.value
    })
  },

  clearFilterInputs() {
    this.ignoreFilterBlurUntil = Date.now() + 300
    this.setFilterState({
      filterFrequencyValue: '',
      filterReactiveValue: '',
      filterResistanceValue: ''
    })
  },

  onFilterResistanceUnitChange(event) {
    this.setFilterState({
      filterResistanceUnitIndex: Number(event.detail.value)
    })
  },

  onFilterReactiveUnitChange(event) {
    const unitIndex = Number(event.detail.value)
    const field = this.data.filterNetworkKey === 'rl'
      ? 'filterInductanceUnitIndex'
      : 'filterCapacitanceUnitIndex'

    this.setFilterState({
      [field]: unitIndex
    })
  },

  onFilterFrequencyUnitChange(event) {
    this.setFilterState({
      filterFrequencyUnitIndex: Number(event.detail.value)
    })
  },

  onFilterValueBlur(event) {
    if (this.ignoreFilterBlurUntil && Date.now() < this.ignoreFilterBlurUntil) return

    const field = event.currentTarget.dataset.field
    const valueKeyMap = {
      frequency: 'filterFrequencyValue',
      reactive: 'filterReactiveValue',
      resistance: 'filterResistanceValue'
    }
    const valueKey = valueKeyMap[field]

    if (this.data.filterComputedKey === field && valueKey && !this.data[valueKey]) return

    this.setData(filterCalculator.normalizeValue(this.data, field, event.detail.value))
  },

  setSmdCodeState(changedData) {
    this.setData(smdCodeCalculator.updateState(this.data, changedData))
  },

  onSmdKindTap(event) {
    const kind = event.currentTarget.dataset.kind
    const kindIndex = (this.data.smdKindOptions || []).findIndex((item) => item.key === kind)
    if (kindIndex < 0) return

    this.setSmdCodeState({
      smdFormatIndex: 0,
      smdFormatKey: '',
      smdKindIndex: kindIndex
    })
  },

  onSmdFormatTap(event) {
    const format = event.currentTarget.dataset.format
    const formatIndex = (this.data.smdFormatOptions || []).findIndex((item) => item.key === format)
    if (formatIndex < 0) return

    this.setSmdCodeState({
      smdFormatIndex: formatIndex,
      smdFormatKey: format
    })
  },

  onSmdCodeInput(event) {
    this.setSmdCodeState({
      smdCodeText: event.detail.value
    })
  },

  clearSmdCodeInput() {
    this.setSmdCodeState({
      smdCodeText: ''
    })
  },

  setCoolingState(changedData) {
    this.setData(refrigerationCalculator.updateState(this.data, changedData))
  },

  onCoolingModeTap(event) {
    const mode = event.currentTarget.dataset.mode
    const modeIndex = (this.data.coolingModeOptions || []).findIndex((item) => item.key === mode)
    if (modeIndex < 0) return

    this.setCoolingState({
      coolingModeIndex: modeIndex
    })
  },

  onCoolingModeChange(event) {
    this.setCoolingState({
      coolingModeIndex: Number(event.detail.value)
    })
  },

  onCoolingInput(event) {
    const field = event.currentTarget.dataset.field
    if (!field) return

    this.setCoolingState({
      [field]: event.detail.value
    })
  },

  clearCoolingInputs() {
    this.setData(refrigerationCalculator.clearInputs(this.data))
  },

  setThreePhasePowerState(changedData) {
    this.setData(threePhasePowerCalculator.updateState(this.data, changedData))
  },

  onThreePhaseConnectionTap(event) {
    const connection = event.currentTarget.dataset.connection
    const connectionIndex = (this.data.threePhaseConnectionOptions || []).findIndex((item) => item.key === connection)
    if (connectionIndex < 0) return

    this.setThreePhasePowerState({
      threePhaseConnectionIndex: connectionIndex
    })
  },

  onThreePhaseInput(event) {
    const field = event.currentTarget.dataset.field
    if (!field) return

    const changedData = {
      [field]: event.detail.value
    }
    if (threePhasePowerCalculator.ELECTRICAL_INPUT_KEYS.includes(field)) {
      changedData.threePhaseElectricalDriver = field
    }
    if (threePhasePowerCalculator.POWER_DRIVER_KEYS.includes(field)) {
      changedData.threePhasePowerDriver = field
    }

    this.setThreePhasePowerState(changedData)
  },

  clearThreePhaseInputs() {
    this.setData(threePhasePowerCalculator.clearInputs(this.data))
  },

  setReactanceState(changedData) {
    this.setData(reactanceCalculator.updateState(this.data, changedData))
  },

  toggleReactanceMode() {
    this.setReactanceState({
      reactanceModeIndex: this.data.reactanceModeKey === 'inductive' ? 0 : 1
    })
  },

  onReactanceFrequencyInput(event) {
    this.setReactanceState({
      reactanceFrequencyValue: event.detail.value
    })
  },

  onReactanceReactiveInput(event) {
    this.setReactanceState({
      reactanceReactiveValue: event.detail.value
    })
  },

  clearReactanceInputs() {
    this.ignoreReactanceBlurUntil = Date.now() + 300
    this.setData(reactanceCalculator.clearInputs(this.data))
  },

  onReactanceFrequencyUnitChange(event) {
    this.setReactanceState({
      reactanceFrequencyUnitIndex: Number(event.detail.value)
    })
  },

  onReactanceReactiveUnitChange(event) {
    const unitIndex = Number(event.detail.value)
    const field = this.data.reactanceModeKey === 'inductive'
      ? 'reactanceInductanceUnitIndex'
      : 'reactanceCapacitanceUnitIndex'

    this.setReactanceState({
      [field]: unitIndex
    })
  },

  onReactanceValueBlur(event) {
    if (this.ignoreReactanceBlurUntil && Date.now() < this.ignoreReactanceBlurUntil) return

    const field = event.currentTarget.dataset.field

    this.setData(reactanceCalculator.normalizeValue(this.data, field, event.detail.value))
  }

}

module.exports = {
  createToolInitialState,
  toolPageHandlers
}
