import AutocompleteMenu from './AutocompleteMenu' import promisify from '../utils/promisify' import supportDom from '../decorators/supportDom' import { debounce, noop } from '../utils'

const defaultRenderMenuItem = row => {

return `
  <div class="item">
    <div class="page-prefix">${row.prefix}</div>
    <div class="page-title">${row.title}</div>
  </div>
`

}

@supportDom export default class Autocomplete {

constructor(dom, options = {}) {
  this.dom = dom
  this.options = options
  this.options.getData = promisify(this.options.getData || noop)
  this.options.renderMenuItem = this.options.renderMenuItem || defaultRenderMenuItem
  this.isCompositing = false
  this.rows = []

  const { dataset } = dom
  const offsetLeft = ('offsetLeft' in dataset) ? parseInt(dataset.offsetLeft, 10) : 0
  const offsetTop = ('offsetTop' in dataset) ? parseInt(dataset.offsetTop, 10) : 0

  this.menu = new AutocompleteMenu({ offsetLeft, offsetTop })
  this.init()
}

init() {
  this.addEvents()
}

renderMenuItem() {
  this.menu.renderMenuItem(this.rows, this.options.renderMenuItem)
}

async getData() {
  const lastKeyword = this.dom.value
  const rows = await this.options.getData({ keyword: lastKeyword })
  if (lastKeyword !== this.dom.value) {
    return
  }
  const { menu } = this
  this.rows = rows
  this.renderMenuItem()

  if (rows.length > 0) {
    this.showMenu()
    return
  }
  menu.hide()
}

showMenu() {
  this.menu.show(this.dom)
}

addEvents() {
  const { dom, menu } = this

  menu.on('click', index => {
    const { itemClick } = this.options
    if (typeof itemClick === 'function') {
      const value = itemClick(this.rows[index])
      this.dom.value = value
      this.menu.hide()
    }
  })

  this.addEvent(dom, 'focus', () => {
    if (this.rows.length === 0) {
      this.getData()
    }
    else {
      this.showMenu()
    }
  })

  this.addEvent(document, 'click', event => {
    const { target } = event
    const inInput = this.dom.contains(target)
    const inMenu = this.menu.dom.contains(target)
    if ((! inInput) && (! inMenu)) {
      this.menu.hide()
    }
  })

  this.addEvent(dom, 'keyup', debounce(() => {
    if (this.isCompositing) {
      return
    }
    this.getData()
  }, 200))

  this.addEvent(dom, 'compositionstart', () => {
    this.isCompositing = true
  })

  this.addEvent(dom, 'compositionend', () => {
    this.getData()
    this.isCompositing = false
  })
}

destroy() {
  this.menu.destroy()
}

}