/**
 * Mixin to handle resize.
 * @mixin ApLayoutMixin
 */

'use strict'

import React, {PropTypes as types} from 'react'
import deepEqual from 'deep-equal'
import defaults from 'defaults'

const LAYOUT_INTERVAL = 80

export class ApLayoutEvent {
  constructor (values) {
    const s = this
    Object.assign(s, values)
  }
}

/** @lends ApLayoutMixin */
const ApLayoutMixin = {

  // --------------------
  // Custom
  // --------------------
  $apLayoutMixed: true,

  /**
   * Reserve layout.
   */
  layout (immidate) {
    const s = this
    let { props } = s
    clearTimeout(s._layoutTimer)
    s._layoutTimer = setTimeout(() => {
      if (!s.isMounted()) {
        return
      }
      let layouts = s.calcLayouts && s.calcLayouts()
      let changed = !deepEqual(s.layouts, layouts)
      if (changed) {
        s.componentWillLayout(layouts)
        s.layouts = layouts
        s.forceUpdate()
        if (props.onLayout) {
          let event = new ApLayoutEvent({ layouts })
          props.onLayout(event)
        }
        s.componentDidLayout(layouts)
      }
    }, immidate ? 0 : LAYOUT_INTERVAL)
  },

  // --------------------
  // Specs
  // --------------------

  propTypes: {
    onLayout: types.func
  },

  // --------------------
  // Lifecycle
  // --------------------

  componentWillMount () {
    const s = this
    if (s.getInitialLayouts) {
      s.layouts = s.getInitialLayouts()
    }
    let noop = () => undefined

    defaults(s, {
      componentWillLayout: noop,
      componentDidLayout: noop
    })
  },
  componentDidMount () {
    const s = this
    if (!s.calcLayouts) {
      console.warn('[ApLayoutMixin] Should implement .calcLayouts()')
    }
    window.addEventListener('resize', s.layout)
    s.layout(true)
  },

  componentWillReceiveProps (nextProps) {
    const s = this
    s.layout()
  },

  componentWillUnmount () {
    const s = this
    clearTimeout(s._layoutTimer)
    window.removeEventListener('resize', s.layout)
    delete s._layoutTimer
  },

  // --------------------
  // Private
  // --------------------

  layouts: null,
  _layoutTimer: null

}

export default Object.freeze(ApLayoutMixin)
