import 'intersection-observer'

import {
  getTargetDataset
} from 'uni-helpers/index'

import {
  findElm
} from './util'

function getRect (rect) {
  return {
    bottom: rect.bottom,
    height: rect.height,
    left: rect.left,
    right: rect.right,
    top: rect.top,
    width: rect.width
  }
}

// 在相交比很小的情况下，Chrome会返回相交为0
function rectifyIntersectionRatio (entrie) {
  const {
    intersectionRatio,
    boundingClientRect: { height: overAllHeight, width: overAllWidth },
    intersectionRect: { height: intersectionHeight, width: intersectionWidth }
  } = entrie

  if (intersectionRatio !== 0) return intersectionRatio

  return intersectionHeight === overAllHeight
    ? intersectionWidth / overAllWidth
    : intersectionHeight / overAllHeight
}

const intersectionObservers = {}

export function requestComponentObserver ({
  reqId,
  component,
  options
}, pageId) {
  let pageVm
  if (pageId._isVue) {
    pageVm = pageId
  } else {
    const pages = getCurrentPages() // 跨平台时，View 层也应该实现该方法，举例 App 上，View 层的 getCurrentPages 返回长度为1的当前页面数组
    const page = pages.find(page => page.$page.id === pageId)
    if (!page) {
      throw new Error(`Not Found：Page[${pageId}]`)
    }
    pageVm = page.$vm
  }
  const $el = findElm(component, pageVm)
  const root = options.relativeToSelector ? $el.querySelector(options.relativeToSelector) : null
  const intersectionObserver = intersectionObservers[reqId] = new IntersectionObserver((entries, observer) => {
    entries.forEach(entrie => {
      UniViewJSBridge.publishHandler('onRequestComponentObserver', {
        reqId,
        res: {
          intersectionRatio: rectifyIntersectionRatio(entrie),
          intersectionRect: getRect(entrie.intersectionRect),
          boundingClientRect: getRect(entrie.boundingClientRect),
          relativeRect: getRect(entrie.rootBounds),
          time: Date.now(),
          dataset: getTargetDataset(entrie.target),
          id: entrie.target.id
        }
      })
    })
  }, {
    root,
    rootMargin: options.rootMargin,
    threshold: options.thresholds
  })
  if (options.observeAll) {
    intersectionObserver.USE_MUTATION_OBSERVER = true
    Array.prototype.map.call($el.querySelectorAll(options.selector), el => {
      if (!el) {
        console.warn(`Node ${options.selector} is not found. Intersection observer will not trigger.`)
        return
      }
      intersectionObserver.observe(el)
    })
  } else {
    intersectionObserver.USE_MUTATION_OBSERVER = false
    const el = $el.querySelector(options.selector)
    if (!el) {
      console.warn(`Node ${options.selector} is not found. Intersection observer will not trigger.`)
      return
    }
    intersectionObserver.observe(el)
  }
}

export function destroyComponentObserver ({
  reqId
}) {
  const intersectionObserver = intersectionObservers[reqId]
  if (intersectionObserver) {
    intersectionObserver.disconnect()
    delete intersectionObservers[reqId]
    UniViewJSBridge.publishHandler('onRequestComponentObserver', {
      reqId,
      reqEnd: true
    })
  }
}
