import type { RootRect } from './types'

export default function getDanmuTop({
  target,
  emits,
  clientWidth,
  clientHeight,
  marginBottom,
  marginTop,
  antiOverlap
}: RootRect): number {
  const danmus = emits
    .filter((item) => item.mode === target.mode && item.top <= clientHeight - marginBottom)
    .sort((prev, next) => prev.top - next.top)

  if (danmus.length === 0) return marginTop

  danmus.unshift({
    top: 0,
    left: 0,
    right: 0,
    height: marginTop,
    width: clientWidth,
    speed: 0,
    distance: clientWidth
  })

  danmus.push({
    top: clientHeight - marginBottom,
    left: 0,
    right: 0,
    height: marginBottom,
    width: clientWidth,
    speed: 0,
    distance: clientWidth
  })

  for (let index = 1; index < danmus.length; index += 1) {
    const item = danmus[index]!
    const prev = danmus[index - 1]!
    const prevBottom = prev.top + prev.height
    const diff = item.top - prevBottom
    if (diff >= target.height) {
      return prevBottom
    }
  }

  const topMap: RootRect['emits'][] = []
  for (let index = 1; index < danmus.length - 1; index += 1) {
    const item = danmus[index]!
    if (topMap.length) {
      const last = topMap[topMap.length - 1]!
      if (last[0]!.top === item.top) {
        last.push(item)
      } else {
        topMap.push([item])
      }
    } else {
      topMap.push([item])
    }
  }

  if (antiOverlap) {
    switch (target.mode) {
      case 0: {
        const result = topMap.find((list) => {
          return list.every((danmu) => {
            if (clientWidth < danmu.distance) return false
            if (target.speed < danmu.speed) return true
            const overlapTime = danmu.right / (target.speed - danmu.speed)
            if (overlapTime > danmu.time!) return true
            return false
          })
        })

        return result && result[0] ? result[0].top : -1
      }
      case 1:
        return -1
      default:
        return -1
    }
  } else {
    switch (target.mode) {
      case 0:
        topMap.sort((prev, next) => {
          const nextMinRight = Math.min(...next.map((item) => item.right))
          const prevMinRight = Math.min(...prev.map((item) => item.right))
          return nextMinRight * next.length - prevMinRight * prev.length
        })
        break
      case 1:
        topMap.sort((prev, next) => {
          const nextMaxWidth = Math.max(...next.map((item) => item.width))
          const prevMaxWidth = Math.max(...prev.map((item) => item.width))
          return prevMaxWidth * prev.length - nextMaxWidth * next.length
        })
        break
      default:
        break
    }

    return topMap[0]?.[0]?.top || -1
  }
}
