import { layers } from "../../modules/layers"

type CallArgs<T extends any> = {
  isIntersecting: boolean,
  target: T,
  pos: FYGE.Point
}

type EventCall<T extends any> = (e?: CallArgs<T>) => any
type OffsetPos = {x: number, y: number}

export class IntersectionObserver<TE extends FYGE.Container> {
  private obCallBack?: (changes: CallArgs<TE>[]) => void
  entries: {
    t: TE,
    offset: OffsetPos
    cb: EventCall<TE>
  }[] = []
  constructor(obCallBack?: (changes: CallArgs<TE>[]) => void) {
    this.entries = []
    this.obCallBack = obCallBack
  }

  flush() {
    const _copy = this.entries.slice(0)
    const tempPoint = new FYGE.Point()
    const result = []
    for (let i = _copy.length - 1; i >= 0; i--) {
      const currItem = _copy[i]
      tempPoint.set(currItem.offset.x, currItem.offset.y)

      const p =  currItem.t.localToGlobal(tempPoint)
      if (p.x >= 0 && p.y >= layers.stageOffsetY && p.x <= layers.stageWidth && p.y <= layers.stageOffsetY + layers.stageHeight) {
        const arg = {
          target: currItem.t,
          isIntersecting: true,
          pos: p
        }
        currItem.cb(arg)

        result.push(arg)
      }
    }

    this.obCallBack && this.obCallBack(result)
  }

  observe<T extends TE>(target: T, offset: OffsetPos={x: 0, y: 0}, cb?: EventCall<T>) {
    this.entries.push({
      t: target,
      offset,
      cb
    })
  }

  unobserve<T extends TE>(target: T) {
    const i = this.entries.findIndex(c => c.t == target)
    i !== -1 && this.entries.splice(i, 1)
  }

  unobserveAll() {
    this.entries.length = 0
  }
}

