/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
import { throttle, extend } from './func'
import { createEvent } from './event'
import config from '../config'

export function getParentScroller (vm) {
  if (!vm) return null
  if (vm._parentScroller) {
    return vm._parentScroller
  }
  function _getParentScroller (parent) {
    if (!parent) { return }
    if (config.scrollableTypes.indexOf(parent.weexType) > -1) {
      vm._parentScroller = parent
      return parent
    }
    return _getParentScroller(parent.$parent)
  }
  return _getParentScroller(vm.$parent)
}

function horizontalBalance (rect, ctRect) {
  return rect.left < ctRect.right && rect.right > ctRect.left
}

function verticalBalance (rect, ctRect) {
  return rect.top < ctRect.bottom && rect.bottom > ctRect.top
}

/**
 * return a data array with two boolean value, which are:
 * 1. visible in current ct's viewport.
 * 2. visible with offset in current ct's viewport.
 */
export function hasIntersection (rect, ctRect, dir, offset) {
  dir = dir || 'up'
  const isHorizontal = dir === 'left' || dir === 'right'
  const isVertical = dir === 'up' || dir === 'down'
  if (isHorizontal && !verticalBalance(rect, ctRect)) {
    return [false, false]
  }
  if (isVertical && !horizontalBalance(rect, ctRect)) {
    return [false, false]
  }
  offset = parseInt(offset || 0) * weex.config.env.scale
  switch (dir) {
    case 'up':
      return [
        rect.top < ctRect.bottom && rect.bottom > ctRect.top,
        rect.top < ctRect.bottom + offset && rect.bottom > ctRect.top - offset
      ]
    case 'down':
      return [
        rect.bottom > ctRect.top && rect.top < ctRect.bottom,
        rect.bottom > ctRect.top - offset && rect.top < ctRect.bottom + offset
      ]
    case 'left':
      return [
        rect.left < ctRect.right && rect.right > ctRect.left,
        rect.left < ctRect.right + offset && rect.right > ctRect.left - offset
      ]
    case 'right':
      return [
        rect.right > ctRect.left && rect.left < ctRect.right,
        rect.right > ctRect.left - offset && rect.left < ctRect.right + offset
      ]
  }
}

/**
 * isElementVisible
 * @param  {HTMLElement}  el    a dom element.
 * @param  {HTMLElement}  container  optional, the container of this el.
 */
export function isElementVisible (el, container, dir, offset) {
  if (!el.getBoundingClientRect) { return false }
  const bodyRect = {
    top: 0,
    left: 0,
    bottom: window.innerHeight,
    right: window.innerWidth
  }
  const ctRect = (container === document.body)
    ? bodyRect : container
    ? container.getBoundingClientRect() : bodyRect
  return hasIntersection(el.getBoundingClientRect(), ctRect, dir, offset)
}

// to trigger the appear/disappear event.
function triggerEvent (elm, handlers, evt, dir) {
  let listener = handlers[evt]
  if (listener && listener.fn) {
    listener = listener.fn
  }
  if (listener) {
    listener(createEvent(elm, evt, {
      direction: dir
    }))
  }
}

/**
 * get all event listeners. including bound handlers in all parent vnodes.
 */
export function getEventHandlers (context) {
  let vnode = context.$vnode
  const handlers = {}
  const attachedVnodes = []
  while (vnode) {
    attachedVnodes.push(vnode)
    vnode = vnode.parent
  }
  attachedVnodes.forEach(function (vnode) {
    const parentListeners = vnode.componentOptions && vnode.componentOptions.listeners
    const dataOn = vnode.data && vnode.data.on
    extend(handlers, parentListeners, dataOn)
  })
  return handlers
}

function getAppearOffset (el) {
  return el && el.getAttribute('appear-offset')
}

function checkHandlers (handlers) {
  return [
    !!(handlers.appear || handlers.disappear),
    !!(handlers.offsetAppear || handlers.offsetDisappear)
  ]
}

/**
 * Watch element's visibility to tell whether should trigger a appear/disappear
 * event in scroll handler.
 */
export function watchAppear (context, fireNow) {
  const el = context && context.$el
  if (!el || el.nodeType !== 1) { return }
  const appearOffset = getAppearOffset(el)

  const handlers = getEventHandlers(context)
  const checkResults = checkHandlers(handlers)
  // no appear or offsetAppear handler was bound.
  if (!checkResults[0] && !checkResults[1]) {
    return
  }

  let isWindow = false
  let container = document.body
  const scroller = getParentScroller(context)
  if (scroller && scroller.$el) {
    container = scroller.$el
  }
  else {
    isWindow = true
  }

  if (fireNow) {
    const visibleData = isElementVisible(el, container, null, appearOffset)
    detectAppear(context, visibleData, null)
  }

  // add current vm to the container's appear watch list.
  if (!container._watchAppearList) {
    container._watchAppearList = []
  }
  container._watchAppearList.push(context)

  /**
   * Code below will only exec once for binding scroll handler for parent container.
   */
  if (container._scrollWatched) {
    return
  }
  container._scrollWatched = true
  const scrollHandler = throttle(event => {
    /**
     * detect scrolling direction.
     * direction only support up & down yet.
     * TODO: direction support left & right.
     */
    const scrollTop = isWindow ? window.pageYOffset : container.scrollTop
    const preTop = container._lastScrollTop
    container._lastScrollTop = scrollTop
    const dir = (scrollTop < preTop
      ? 'down' : scrollTop > preTop
      ? 'up' : container._prevDirection) || null
    container._prevDirection = dir
    const watchAppearList = container._watchAppearList || []
    const len = watchAppearList.length
    for (let i = 0; i < len; i++) {
      const vm = watchAppearList[i]
      const el = vm.$el
      const appearOffset = getAppearOffset(el)
      const visibleData = isElementVisible(el, container, dir, appearOffset)
      detectAppear(vm, visibleData, dir)
    }
  }, 25, true)
  container.addEventListener('scroll', scrollHandler, false)
}

/**
 * trigger a disappear event.
 */
export function triggerDisappear (context) {
  return detectAppear(context, [false, false])
}

/**
 * decide whether to trigger a appear/disappear event.
 * @param {VueComponent} context
 * @param {boolean} visible
 * @param {string} dir
 */
export function detectAppear (context, visibleData, dir = null, appearOffset) {
  const el = context && context.$el
  const [visible, offsetVisible] = visibleData
  if (!el) { return }
  const handlers = getEventHandlers(context)
  /**
   * No matter it's binding appear/disappear or both of them. Always
   * should test it's visibility and change the context/._visible.
   * If neithor of them was bound, then just ignore it.
   */
  /**
   * if the component hasn't appeared for once yet, then it shouldn't trigger
   * a disappear event at all.
   */
  if (context._appearedOnce || visible) {
    if (context._visible !== visible) {
      if (!context._appearedOnce) {
        context._appearedOnce = true
      }
      context._visible = visible
      triggerEvent(el, handlers, visible ? 'appear' : 'disappear', dir)
    }
  }
  if (context._offsetAppearedOnce || offsetVisible) {
    if (context._offsetVisible !== offsetVisible) {
      if (!context._offsetAppearedOnce) {
        context._offsetAppearedOnce = true
      }
      context._offsetVisible = offsetVisible
      triggerEvent(el, handlers, offsetVisible ? 'offsetAppear' : 'offsetDisappear', dir)
    }
  }
}
