$ = jQuery
context = window
logger = context.JK.logger
rest = context.JK.Rest()
EVENTS = context.JK.EVENTS

BrowserMediaActions = @BrowserMediaActions

Howler._enableiOSAudio()

@BrowserMediaStore = Reflux.createStore(
  {
    listenables: BrowserMediaActions
    audio: null
    loaded: false
    loading: false
    playing: false
    paused: false
    load_error: false
    id: null
    media_type: null
    cachedAudio: []
    cache_size: 10
    preload: true

    playbackState:(position, time) ->
      state = {}
      if @playing
        state.playbackState = 'play_start'
      else if @paused
        state.playbackState = 'play_pause'
      else
        state.playbackState = 'play_stop'

      state.playbackStateChanged = !@state? || @state.isPlaying != @playing || @state.paused != @paused
      state.positionUpdateChanged = !@state? || @state.positionMs != position
      state.currentTimeChanged = !@state? || @state.time != time
      state

    changed: () ->
      position = @onGetPlayPosition()
      time = context.JK.prettyPrintSeconds(parseInt(position / 1000))
      playbackState = @playbackState(position, time)

      # XXX: how to deal with duration? no mention in Howler API

      target = {id: @id, isPlaying: @playing, loaded: @loaded, paused: @paused, loading: @loading, load_error: @load_error, positionMs: position, time: time, durationMs: @onGetPlayDuration()}
      $.extend(true, target, playbackState)
      @state = target
      @trigger(@state)

    onLoad: (id, urls, media_type) ->

      if @loading
        logger.error("you can't switch to different audio while loading due to weird errors seen in Howler")
        window.location.reload()
        return

      if @audio
        @audio.stop()
        @loaded = false
        @loading = false
        @playing = false
        @paused = false
        @load_error = false

      @audio = null
      @id = id
      @media_type = media_type
      @loading = @preload
      @playing = false
      @paused = false


      for cacheItem in @cachedAudio
        if cacheItem.id == id
          # items in our own cache are only there if we saw that it fully loaded
          @audio = cacheItem.audio
          @loaded = true
          @loading = false

      unless @audio?
        @audio = new Howl({
          src: urls,
          autoplay: false,
          loop: false,
          volume: 1,
          preload: @preload,
          onend: @onAudioEnded,
          onload: @onAudioLoaded,
          onloaderror: @onAudioLoadError,
          onpause: @onAudioPause,
          onplay: @onAudioPlay
        })
        @audio.jkid = id

      @changed()

    onPlay: () ->
      logger.debug("BrowerMediaStore:play")
      if @audio
        @playing = true
        @paused = false
        @audio.play()

        try
          if !@audio.recorded_play
            rest.postUserEvent({name: @media_type + '_play'}) if @media_type?
            context.stats.write('web.' + @media_type + '.play', {
              value: 1,
              user_id: context.JK.currentUserId,
              user_name: context.JK.currentUserName
            }) if @media_type

            @audio.recorded_play = true
        catch e
          logger.warn("BrowserMediaStore: unable to post user event")

    onPause: () ->
      if @audio
        @playing = false
        @paused = true
        @audio.pause()

    onStop: () ->
      if @audio
        @playing = false
        @paused = false
        try
          @audio.pause()
        catch e
          @logger.info("unable to pause on stop", e)
        try
          @audio.seek(0)
        catch e
          @logger.info("unable to seek to beginning on stop", e)


    onSeek: (pos) ->
      if @audio
        console.log("seek time", pos)
        @audio.seek(pos / 1000)

    onGetPlayPosition: () ->
      if @audio
        try
          position = @audio.seek()
          if position == @audio
            return 0
          position * 1000
        catch e
          return 0
      else
        0

    onGetPlayDuration: () ->
      if @audio
        # XXX : how to determine duration?
        try
          duration = @audio.duration()
          return Math.round(duration) * 1000
        catch e
          return 0
      else
        0

    onAudioEnded: () ->
      logger.debug("onAudioEnded")
      @playing = false
      @changed()

    onAudioLoaded: () ->
      logger.debug("onAudioLoaded", arguments)
      @loaded = true
      @loading = false

      # add audio to cache, and ageout cached audio items if more than 10 \
      if @cachedAudio.length >= @cache_size
        audio = @cachedAudio.shift()
        try
          audio.audio.unload()
        catch e
          logger.error("unable to unload aged audio", @audio)

      @cachedAudio.push({id: @audio.jkid, audio: @audio})
      @changed()

    onAudioLoadError: () ->
      logger.debug("onAudioLoadError", arguments)
      @load_error = true
      @loading = false
      @changed()

    onAudioPause: () ->
      logger.debug("onAudioPause")

      @changed()

    onAudioPlay: () ->
      logger.debug("onAudioPlay")
      @playing = true
      @paused = false
      @changed()

  }
)