<slot></slot>
<script>
  import { virtualListStore } from './virtualListStore'
  import throttle from 'lodash-es/throttle'
  import { isFullscreen, attachFullscreenListener, detachFullscreenListener } from '../../_utils/fullscreen'
  import { mark, stop } from '../../_utils/marks'
  import { scheduleIdleTask } from '../../_utils/scheduleIdleTask'
  import { isMobile } from '../../_utils/isMobile'
  import { doubleRAF } from '../../_utils/doubleRAF'

  const SCROLL_EVENT_DELAY = 300

  export default {
    oncreate () {
      mark('onCreate VirtualListContainer')
      let {
        realm,
        containerQuery
      } = this.get()
      this.store.setCurrentRealm(realm)
      let node = document.querySelector(containerQuery)
      this.setupScroll(node)
      this.setupFullscreen()
      let { scrollTop } = this.store.get()
      if (scrollTop > 0) {
        this.observe('allVisibleItemsHaveHeight', allVisibleItemsHaveHeight => {
          console.log('allVisibleItemsHaveHeight', allVisibleItemsHaveHeight)
          let { initializedScrollTop } = this.get()
          if (!initializedScrollTop && allVisibleItemsHaveHeight && node) {
            this.set({'initializedScrollTop': true})
            mark('set scrollTop')
            console.log('forcing scroll top to ', scrollTop)
            node.scrollTop = scrollTop
            stop('set scrollTop')
            doubleRAF(() => {
              console.log('initialized VirtualList')
              this.fire('initialized')
            })
          }
        })
      } else {
        this.fire('noNeedToScroll')
        this.observe('allVisibleItemsHaveHeight', allVisibleItemsHaveHeight => {
          if (allVisibleItemsHaveHeight) {
            console.log('initialized VirtualList')
            this.fire('initialized')
          }
        })
        this.store.setForRealm({
          scrollHeight: node.scrollHeight,
          offsetHeight: node.offsetHeight
        })
      }
      stop('onCreate VirtualListContainer')
    },
    ondestroy () {
      this.teardownScroll()
      this.teardownFullscreen()
      this.store.setCurrentRealm(null)
    },
    store: () => virtualListStore,
    methods: {
      setupScroll (node) {
        if (!node) {
          return
        }
        this.scrollListener = throttle(event => {
          let { fullscreen } = this.get()
          if (fullscreen) {
            return
          }
          this.onScroll(event)
        }, SCROLL_EVENT_DELAY, {
          leading: true,
          trailing: true
        })
        node.addEventListener('scroll', this.scrollListener)
      },
      teardownScroll () {
        let { containerQuery } = this.get()
        let node = document.querySelector(containerQuery)
        if (node) {
          node.removeEventListener('scroll', this.scrollListener)
        }
      },
      setupFullscreen () {
        this.onFullscreenChange = this.onFullscreenChange.bind(this)
        attachFullscreenListener(this.onFullscreenChange)
      },
      teardownFullscreen () {
        detachFullscreenListener(this.onFullscreenChange)
      },
      onScroll (event) {
        let { scrollTop, scrollHeight } = event.target

        // On mobile devices, this can make scrolling more responsive. On
        // desktop browsers... it's probably overkill, and can lead to a
        // checkerboarding issue ("I just scrolled, why is it blank for 5 seconds?").
        let runTask = isMobile() ? scheduleIdleTask : requestAnimationFrame

        runTask(() => {
          mark('onScroll -> setForRealm()')
          this.store.setForRealm({scrollTop, scrollHeight})
          stop('onScroll -> setForRealm()')
        })
      },
      onFullscreenChange () {
        mark('onFullscreenChange')
        console.log('is fullscreen? ', isFullscreen())
        this.set({ fullscreen: isFullscreen() })
        stop('onFullscreenChange')
      }
    },
    computed: {
      // TODO: bug in svelte/store – the observer in oncreate() never get removed without this hack
      allVisibleItemsHaveHeight: ($allVisibleItemsHaveHeight) => $allVisibleItemsHaveHeight
    }
  }
</script>