const settingsService = require('../../store/settings-store.js')
const themeService = require('../../store/theme-store.js')
const bootloaderService = require('../../features/bootloader/service.js')
const transport = require('../../transport/ble-core.js')
const {
  createPageToast
} = require('../../utils/page-toast.js')
const {
  createToolInitialState,
  toolNavigation,
  toolPageHandlers
} = require('../../features/tools/index.js')
const {
  getSettingsPageState
} = require('../../features/settings/view-model.js')
const protocolImplementation = require('../../features/settings/protocol-implementation.js')
const {
  getWxApi
} = require('../../utils/base-utils.js')

Page({
  data: {
    ...getSettingsPageState(),
    ...protocolImplementation.getState(),
    ...createToolInitialState(),
    activeSettingsTitle: '',
    activeSettingsView: ''
  },

  onLoad() {
    this.pageToast = createPageToast(this, this.data)
    this.crcFileBytes = null
    settingsService.init()
    themeService.init()
    bootloaderService.init()

    this.unsubscribeSettings = settingsService.subscribe((settingsState) => {
      this.setData(getSettingsPageState(settingsState, themeService.getState()))
    })
    this.unsubscribeTheme = themeService.subscribe((themeState) => {
      this.setData(getSettingsPageState(settingsService.getState(), themeState))
    })
    this.unsubscribeTransport = transport.subscribe((transportState) => {
      this.setData(getSettingsPageState(
        settingsService.getState(),
        themeService.getState(),
        transportState,
        bootloaderService.getState()
      ))
    })
    this.unsubscribeBootloader = bootloaderService.subscribe((bootloaderState) => {
      this.setData(getSettingsPageState(
        settingsService.getState(),
        themeService.getState(),
        transport.getState(),
        bootloaderState
      ))
    })
  },

  onTabItemTap() {
    this.backToSettingsHome()
  },

  onShow() {
    if (this.pageToast) {
      this.pageToast.setActive(true)
    }

    this.setData(getSettingsPageState())
  },

  onHide() {
    if (this.pageToast) {
      this.pageToast.setActive(false)
    }
  },

  onUnload() {
    if (this.pageToast) {
      this.pageToast.destroy()
      this.pageToast = null
    }

    if (this.unsubscribeSettings) {
      this.unsubscribeSettings()
      this.unsubscribeSettings = null
    }

    if (this.unsubscribeTheme) {
      this.unsubscribeTheme()
      this.unsubscribeTheme = null
    }

    if (this.unsubscribeTransport) {
      this.unsubscribeTransport()
      this.unsubscribeTransport = null
    }

    if (this.unsubscribeBootloader) {
      this.unsubscribeBootloader()
      this.unsubscribeBootloader = null
    }
  },

  onNightModeEnabledChange(event) {
    settingsService.setNightModeEnabled(!!event.detail.value)
  },

  onNightModeFollowSystemChange(event) {
    settingsService.setNightModeFollowSystem(!!event.detail.value)
  },

  onSettingsDraftInput(event) {
    const field = event && event.currentTarget && event.currentTarget.dataset
      ? event.currentTarget.dataset.field
      : ''
    if (!field) return

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

  onModbusSlaveAddressBlur(event) {
    settingsService.setModbusSlaveAddress(event.detail.value)
  },

  onProtocolModeChange(event) {
    const option = this.data.protocolOptions[Number(event.detail.value)]
    if (!option) return

    settingsService.setProtocolMode(option.key)
  },

  onParameterAutoPollChange(event) {
    settingsService.setParameterAutoPollEnabled(!!event.detail.value)
  },

  onParameterPollIntervalBlur(event) {
    settingsService.setParameterPollInterval(event.detail.value)
  },

  onParameterMaxPacketLengthBlur(event) {
    settingsService.setParameterMaxPacketLength(event.detail.value)
  },

  openToolEntry(event) {
    const view = event.currentTarget.dataset.view
    if (!toolNavigation.isToolView(view)) return

    if (this.pageToast) this.pageToast.clear()
    this.setData({
      activeSettingsTitle: toolNavigation.getToolTitle(view),
      activeSettingsView: view
    })
  },

  openProtocolImplementation() {
    if (this.pageToast) this.pageToast.clear()
    this.setData({
      activeSettingsTitle: protocolImplementation.TITLE,
      activeSettingsView: protocolImplementation.VIEW_ID,
      ...protocolImplementation.getState(this.data.storageProtocolImplementationActiveIndex)
    })
  },

  selectProtocolImplementationFile(event) {
    const index = Number(event.currentTarget.dataset.index)

    this.setData(protocolImplementation.getState(index))
  },

  copyProtocolImplementationFile(event) {
    const index = event && event.currentTarget && event.currentTarget.dataset
      ? Number(event.currentTarget.dataset.index)
      : this.data.storageProtocolImplementationActiveIndex
    const text = protocolImplementation.getSourceText(index)
    if (!text) {
      if (this.pageToast) this.pageToast.show('源码暂未提供')
      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: () => {
        const file = protocolImplementation.getState(index).storageProtocolImplementationActiveFile
        if (this.pageToast) this.pageToast.show(`已复制 ${file.name}`)
      }
    })
  },

  backToSettingsHome() {
    if (this.pageToast) this.pageToast.clear()
    this.setData({
      activeSettingsTitle: '',
      activeSettingsView: ''
    })
  },

  chooseFirmwareFile() {
    if (this.data.isBootloaderBusy) return

    bootloaderService.chooseFirmwareFile('auto')
  },

  startFirmwareUpgrade() {
    if (!this.data.connectedDevice || !this.data.isFirmwareReady || this.data.isBootloaderBusy) return

    bootloaderService.startUpgrade()
  },

  readProgramChecksum() {
    if (!this.data.connectedDevice || this.data.isBootloaderBusy) return

    bootloaderService.readProgramChecksum()
  },

  handshakeBootloader() {
    if (!this.data.connectedDevice || this.data.isBootloaderBusy) return

    bootloaderService.sendHandshakeKeepAlive()
  },

  exitBootloader() {
    if (!this.data.connectedDevice || this.data.isBootloaderBusy) return

    bootloaderService.exitBootloader()
  },

  ...toolPageHandlers
})
