import { updateInstanceInfo, updateVerifyCredentialsForInstance } from '../../_actions/instances'
import { updateLists } from '../../_actions/lists'
import { createStream } from '../../_actions/streaming'
import { updateCustomEmojiForInstance } from '../../_actions/emoji'
import { addStatusesOrNotifications } from '../../_actions/addStatusOrNotification'
import { getTimeline } from '../../_api/timelines'

export function instanceObservers (store) {
  // stream to watch for home timeline updates and notifications
  let currentInstanceStream

  store.observe('currentInstance', async (currentInstance) => {
    if (!process.browser) {
      return
    }
    if (currentInstanceStream) {
      currentInstanceStream.close()
      currentInstanceStream = null
      if (process.env.NODE_ENV !== 'production') {
        window.currentInstanceStream = null
      }
    }
    if (!currentInstance) {
      return
    }
    updateVerifyCredentialsForInstance(currentInstance)
    updateInstanceInfo(currentInstance)
    updateCustomEmojiForInstance(currentInstance)
    updateLists()

    await updateInstanceInfo(currentInstance)

    let currentInstanceIsUnchanged = () => {
      let { currentInstance: newCurrentInstance } = store.get()
      return newCurrentInstance === currentInstance
    }

    if (!currentInstanceIsUnchanged()) {
      return
    }

    let { currentInstanceInfo } = store.get()
    if (!currentInstanceInfo) {
      return
    }

    let homeTimelineItemIds = store.getForTimeline(currentInstance,
      'home', 'timelineItemIds')
    let firstHomeTimelineItemId = homeTimelineItemIds && homeTimelineItemIds[0]
    let notificationItemIds = store.getForTimeline(currentInstance,
      'notifications', 'timelineItemIds')
    let firstNotificationTimelineItemId = notificationItemIds && notificationItemIds[0]

    let onOpenStream = async () => {
      if (!currentInstanceIsUnchanged()) {
        return
      }

      // fill in the "streaming gap" – i.e. fetch the most recent 20 items so that there isn't
      // a big gap in the timeline if you haven't looked at it in awhile
      async function fillGap (timelineName, firstTimelineItemId) {
        if (!firstTimelineItemId) {
          return
        }
        let newTimelineItems = await getTimeline(currentInstance, accessToken,
          timelineName, null, firstTimelineItemId)
        if (newTimelineItems.length) {
          addStatusesOrNotifications(currentInstance, timelineName, newTimelineItems)
        }
      }

      await Promise.all([
        fillGap('home', firstHomeTimelineItemId),
        fillGap('notifications', firstNotificationTimelineItemId)
      ])
    }

    let { accessToken } = store.get()
    let streamingApi = currentInstanceInfo.urls.streaming_api
    currentInstanceStream = createStream(streamingApi,
      currentInstance, accessToken, 'home', onOpenStream)

    if (process.env.NODE_ENV !== 'production') {
      window.currentInstanceStream = currentInstanceStream
    }
  })
}