=begin
  Summary of icecast implementation:

  mount lock locations:
  * IcecastMount.listener_add
  * IcecastMount.listener_remove
  * IcecastMount.source_up
  * IcecastMount.source_down
  * IcecastSourceCheck on each stale IcecastMount

  sourced_needs_changing_at behavior:
  * set to Time.now if first listener comes in (current listeners==0 as they join)
  * set to Time.now if last listener leaves (current listeners == 1 as they leave)
  * set to nil if source begins
  * set to nil if source ends


  * a session's clients gets requested to start a source if one of:
  ** an IcecastMount is saved and listeners go above 0 and not currently sourced
  ** an IcecastSourceCheck finds a IcecastMount with a stale sourced_needs_changing_at and mount.listeners > 0 && !mount.sourced

  * a session's clients get requested to stop a source if
  ** an IcecastSourceCheck finds a IcecastMount with a stale sourced_needs_changing_at and mount.listeners == 0 && mount.sourced
=end

class ApiIcecastController < ApiController
  before_filter :local_only, :only => [:test]
  before_filter :parse_mount, :only => [:mount_add, :mount_remove, :listener_add, :listener_remove]
  before_filter :api_signed_in_user, :only => [ :create_source_change ]

  # each request will have this in it, if it's icecast.
  #user-agent = Icecast 2.3.3


  respond_to :json

  def test
    puts "========= GOT IT======="
    render text: 'GOT IT', :status => :ok
  end

  def mount_add
    mount = IcecastMount.find_by_name!(@mount_id)
    mount.source_up

    render text: '', :status => :ok
  end

  def mount_remove
    mount = IcecastMount.find_by_name!(@mount_id)
    mount.source_down

    render text: '', :status => :ok
  end

  def listener_add
    client = params[:client] # icecast internal id, e.g. 149
    user = params[:user] # basic auth in the request sent to icecast
    pass = params[:pass] # basic auth in the request sent to icecast
    remote_ip = params[:ip]
    remote_user_agent = params[:agent]

    mount = IcecastMount.find_by_name(@mount_id)

    mount.listener_add if mount

    render text: '', :status => :ok
  end

  def listener_remove
    client = params[:client] # you can use this to correlate the listener_add...
    user = params[:user] # or user/pass (icecast is storing these as well and reflects them back)
    pass = params[:pass]
    duration = params[:duration] # seconds connected to the listen stream

    mount = IcecastMount.find_by_name(@mount_id)
    mount.listener_remove if mount

    render text: '', :status => :ok
  end

  # info reported by the client to the server letting us track what's going on at a deeper level
  def create_source_change
    mount = IcecastMount.find(params[:id])

    @source_change = IcecastSourceChange.new
    @source_change.source_direction = params[:source_direction]
    @source_change.user = current_user
    @source_change.client_id = params[:client_id]
    @source_change.success = params[:success]
    @source_change.reason = params[:reason]
    @source_change.detail = params[:detail]
    @source_change.mount = mount
    @source_change.change_type = IcecastSourceChange::CHANGE_TYPE_CLIENT
    @source_change.save

    if @source_change.errors.any?
      response.status = :unprocessable_entity
      respond_with @source_change
    else
      source_change_json = Rabl::Renderer.json(@source_change, 'api_icecast/source_change_notification')
      SubscriptionMessage.mount_source_change(mount, source_change_json)
      render :json => {}, :status => 200
    end
  end

  def show
    @mount = IcecastMount.find(params[:id])

    respond_with @mount, responder: ApiResponder
  end

  protected
  def local_only
    request.local?
  end


  def parse_mount()
    mount = params[:mount]
    # Example A
    # browser:  http://icecast/a
    # mount: /a
    #
    # Example B
    # browser:  http://icecast/a?dog=legs&mump
    # mount: /a?dog=legs&mump

    # browser:  http://icecast/a#bleh
    # mount: /a

    uri = URI(mount)
    @mount_id = uri.path
    @mount_params = Rack::Utils.parse_query(uri.query)
  end
end
