import { dragEvent } from '../../utils'
import { globalClick, getRect } from '../../utils'

interface Options<T> {
  elWrapper: HTMLElement
  elHandle:  HTMLElement
  value: number
  adapter: T
}

class NormalDragger<T> {
  private rect: any
  private elWrapper: HTMLElement
  private elHandle:  HTMLElement
  private value: number
  private height: number
  private adapter: any
  private startTop: number
  private handleHeight: number

  constructor(options: Options<T>) {
    this.rect = getRect(options.elWrapper)
    this.elWrapper = options.elWrapper
    this.elHandle = options.elHandle
    this.value = options.value
    this.height = this.rect.height - 4
    this.startTop = 0
    this.adapter = options.adapter
    this.handleHeight = (this.value / 100) * this.height
    this.setHeight()
    this.dragInit()
    globalClick((e: MouseEvent & { path: Node[] } ) => {
      if (this.elWrapper?.parentNode && !e.path.includes(this.elWrapper.parentNode)) {
        this.adapter.toggleBar(false)
        this.elWrapper.classList.remove('high-warning')
      }
    })
  }

  // change slide height, and emit value
  setHeight() {
    if (this.elHandle)
    this.elHandle.style.height = `${this.handleHeight}px`
    this.adapter.emitValue('input', this.value)
    this.adapter.emitValue('change', this.value)
  }

  // get slide percent height
  getValue() {
    const value = (this.handleHeight / this.height) * 100
    return ~~value
  }

  // toggle hight-warning class
  handleHighWarning() {
    const highWarning = this.adapter.getValue('highWarning')
    if (highWarning <= 0) return
    if (this.value > highWarning) {
      this.elWrapper && this.elWrapper.classList.add('high-warning')
    } else {
      this.elWrapper && this.elWrapper.classList.remove('high-warning')
    }
  }

  // init slider drag event
  dragInit() {
    const dragConfig = {
      dragMove: (e: MouseEvent) => {
        this.dragMove(e)
      },
      dragStop: (e: MouseEvent) => {
        this.dragMove(e)
      }
    }
    dragEvent(this.elWrapper, dragConfig)
  }

  // drag event handler
  dragMove(e: MouseEvent) {
    const mouseY = e.clientY - this.rect.top

    let height = this.height - mouseY

    height = Math.min(height, this.height)
    height = Math.max(height, 0)

    this.handleHeight = height
    this.value = this.getValue()
    this.setHeight()
    this.handleHighWarning()
  }
}
export default NormalDragger
