import { tickUrl, tockUrl } from '/src/constant/audios'
import eventemitter3 from 'eventemitter3'
import state from '/src/pages/detail/state'
import { Howl } from 'howler'
import { browser } from '/src/helpers/utils'
import { nextTick } from '@vue/runtime-core'

const browserInfo = browser()

// 兼容调速
export const getTickTime = (speed: number) => ((browserInfo.huawei ? 0.2 : 0.1) / speed) * 1000

// https://github.com/Tonejs/Tone.js/issues/784 部分ios上可能存在问题

let htick: any = new Howl({
  src: tickUrl,
  format: ['mp3'],
})

let htock: any = new Howl({
  src: tockUrl,
  format: ['mp3'],
})

export default class Player {
  ticks: HTMLAudioElement[] = []

  event = new eventemitter3()

  isRuning = false

  isNeedStop = false

  constructor(dots?: number, speed?: number) {}

  getTickByDots = (dots: number, starttime: number) => {
    return Array.from(Array(dots)).map((item, index) => {
      const data = {
        time: `0:${(starttime + index) * 1.4}`,
        note: index === 0 ? 'C5' : 'c4',
        velocity: 1,
        index: index + starttime,
      }
      return data
    })
  }

  formatTick = (dots: number, repeat: number) => {
    const ticks = []
    for (let i = 0; i < repeat; i++) {
      ticks.push(...this.getTickByDots(dots, i * dots))
    }
    return ticks
  }

  async startTick(times: any[], speed: number, dots: number, repeat: number) {
    let activeIndex = 0
    const nuxtTick = () => {
      const player = activeIndex % times.length === 0 ? htick : htock
      if (!this.isNeedStop) {
        player.play()
        console.log(player)
      }
      if (activeIndex < times.length - 1) {
        timeTick()
      }
      if (activeIndex < dots * repeat) {
        this.event.emit('tick', activeIndex)
      }
      if (activeIndex === dots * repeat - 1) {
        setTimeout(() => {
          this.isRuning = false
          this.event.emit('stop')
          console.log('tick stop')
          this.part?.clear()
        }, 450 / speed)
      }
      activeIndex++
    }

    const timeTick = () => {
      if (!this.isNeedStop) {
        setTimeout(() => {
          try {
            nuxtTick()
          } catch (error) {
            console.log('timeTickError', error)
          }
        }, 666.6 / speed)
      }
    }
    nuxtTick()
  }

  part: any = null

  async setAudioMode(dots: number, speed: number, repeat = 1) {
    await nextTick()
    if (this.isRuning) {
      return
    }
    this.isRuning = true
    const times = this.formatTick(dots, repeat)
    this.startTick(times, speed, dots, repeat)
  }

  async start(dots: number, speed: number, repeat = 1) {
    this.isNeedStop = false
    this.setAudioMode(dots, speed, repeat)
  }

  destroy() {
    this.ticks = []
    this.event.emit('destroy')
    console.log('destroy')
    state.activeTick = -1
    state.activeTickRepeat = 1
    this.event.removeAllListeners()
    this.isRuning = false
    this.isNeedStop = true
    if (this.part) {
      this.part.clear()
      this.part = null
    }
  }
}
