/* ======== /static/js/config.js ======== */

var AWF_CONFIG = {
   "base_url" : "http://amiestreet.com",
   "base_url_secure" : "https://amiestreet.com",
   "build_type" : "production",
   "fb_api_key" : "34362669133f7325de27c332bd1712fe"
};/* ======== /static/js/amie/main.js ======== */

(function ($) {
/**
* Initialize the global Amie namespace
*/

// Register Amie namespace
window.Amie = {};
var Amie = window.Amie;
window.Amie.UI = {};
var UI = window.Amie.UI;
window.Amie.AS = {};
var AS = window.Amie.AS;

Amie.FlashMessenger = {
	close: function(){
		$('#flash-message-box').hide();
	}
}

Amie.selectNewTab = function(acfIds){
    var id = (acfIds.indexOf(',')>-1) ? acfIds.split(',')[0] : acfIds;
    var maps = {'home':'home','browse-tab':'browse_music','newreleases-tab':'new_releases','deals-tab':'special_deals','amietop-tab':'amie_top','recommendations-tab':'recommendations','playlists-tab':'playlists'};
    var tab = $('#navigation').find('li.'+maps[id]);
    tab.siblings('li').removeClass('selected');
    tab.addClass('selected');
}

Amie.updateCartItemCount = function(n){
    $('a.cart-link').html('Your Cart ('+n+')');
}
})(jQuery);


$.fbconnect = {};
$.fbconnect.loaded = (typeof FB == "object");
$.fbconnect.loadInProgress = false;
$.requireFacebook = function(f){
	$.console.log('FBCONNECT: requireFacebook called');
	$.console.log('FBCONNECT: Loaded? '+$.fbconnect.loaded);
	$.console.log('FBCONNECT: Load in progress? '+$.fbconnect.loadInProgress);
    if($.fbconnect.loaded){
    	 f();
    	 return;
    }
    $(document).one('fbconnect.ready', f);
    if($.fbconnect.loadInProgress){
    	$.console.log('FBCONNECT: Its already loading.  Just chillax! Your closure has been queued');
        return;
    }
    
    $.fbconnect.loadInProgress = true;
    $('#fb_loader').show();
    $('body').append('<div id="FB_HiddenContainer" style="position:absolute; top:-10000px; left:-10000px; width:0px; height:0px;"></div>');
    var useSecure = ("https" == document.location.protocol);
    var xdReceiver = (useSecure ? AWF_CONFIG.base_url_secure : AWF_CONFIG.base_url)+"/static/html/xd_receiver.html";
    var s = document.createElement('script');
    s.src = (useSecure ? 
             "https://www.connect.facebook.com/js/api_lib/v0.4/FeatureLoader.js.php" :
             "http://static.ak.connect.facebook.com/js/api_lib/v0.4/FeatureLoader.js.php");
    s.type = 'text/javascript';
    s.onload = s.onreadystatechange = function(){
        FB.init(AWF_CONFIG.fb_api_key, xdReceiver);
        FB.ensureInit(function(){
            $.fbconnect.loaded = true;
            $.fbconnect.loadInProgress = false;
            $('#fb_loader').hide();
            $(document).trigger('fbconnect.ready');
        });
        $.console.log('FBCONNECT: Everything loaded and ready to go!');
    };
    $.console.log('FBCONNECT: Appending featureloader');
    document.getElementsByTagName('head')[0].appendChild(s);
}

$(document).bind('amie.ready', function(){
	var f = 0;
    $.each(
        ["name","profile-pic","login-button","multi-friend-selector","request-form","serverfbml"],
        function(){
        	f += document.getElementsByTagName('fb:'+this).length;
        }
    );
    if(f > 0){$.requireFacebook(function(){FB.XFBML.Host.parseDomTree();});}
    // this has to be suspended like this because FB is not defined until it's loaded
});
/************************
Crazy jQuery.bind rewriting
************************/
/*
jQuery.aop.around( {target: jQuery, method: 'bind'}, function (invocation) {
    $.log('Arguments are ', invocation.arguments);
    return invocation.proceed();
});
*/

/*****************
Mini jQuery Helpers
******************/

jQuery.log = function () {
    try{
        console.log.apply(console, arguments);
    } catch (e) {}
};
jQuery.fn.log = function () {
    jQuery.log.apply(jQuery, arguments);
    return this;
}

jQuery.info = function () {
    try {
        console.info.apply(console, arguments);
    } catch (e) {}
};
jQuery.fn.info = function () {
    jQuery.info.apply(jQuery, arguments);
    return this;
}

jQuery.debug = function () {
    try {
        console.debug.apply(console, arguments);
    } catch (e) {}
};
jQuery.fn.debug = function () {
    jQuery.debug.apply(jQuery, arguments);
    return this;
}




/**************************************
Helpful functions that should be in javascript!
***************************************/

if (!window.isEmpty) {
    window.isEmpty = function (obj) {
        for (var nil in obj)
            return false;
        return true;
    };
}

if (!Array.prototype.some) {
  Array.prototype.some = function(fun /*, thisp*/) {
    var len = this.length;
    if (typeof fun != "function")
      throw new TypeError();

    var thisp = arguments[1];
    for (var i = 0; i < len; i++) {
      if (i in this &&
          fun.call(thisp, this[i], i, this))
        return true;
    }

    return false;
  };
}

/**
 * Triggered by SWFObject when you dont have the required version or at all.
 */
$(document).bind('amie.bad_flash', function(){
	$(document).data('badFlash', true);
});
$(document).ready(function(){
	$('a.open-window').live('click',function(e){
	    var t = false;
        try{
            t = (e.button == 2);
        }
        catch(except){}
        if(!t){
		    window.open(this.href);
		    return false;
        }
	});
	$('.artist-pic').live('mouseover', function(e){
	    if(!$('.hi-res').is(':visible')){
	       $('.hi-res').show();
	    }
	});
	$('.artist-pic').live('mouseout', function(e){
	    if($('.hi-res').is(':visible')){
            $('.hi-res').hide();
	    }
    });
    // Note: doing the find is much much faster as sizzle and querySelectorAll are right to left
    $('.share > .social_icon_list > li.email').find('a').live('click', function(){
         var url='mailto:';
         var body='';
         var subject='';
         body='body='+encodeURIComponent($(this).attr('title') + ' '+$(this).attr('href'));
         subject='subject='+encodeURIComponent($(this).attr('title')+' on AmieStreet.com');
         url+='?'+body+'&'+subject;
         $(this).attr('href',url);
    });
    
    var openShareWindow = function(url,name,height,width){
        var left = parseInt((screen.availWidth/2) - (width/2));
        var top = parseInt((screen.availHeight/2) - (height/2));
        if(window.open(url, name,'height='+height+',width='+width+',top='+top+',left='+left)){
            return false;
        }
    };
    
    $('.share > .social_icon_list > li.facebook').find('a').live('click', function(){
        return openShareWindow($(this).attr('href'),'sharef',350,600);
    });
    $('.share > .social_icon_list > li.twitter').find('a').live('click', function(){
        return openShareWindow($(this).attr('href'),'twitter',350,600);
    });
    $('.share > .social_icon_list > li.gmail').find('a').live('click', function(){
        return openShareWindow($(this).attr('href'),'gmail',350,600);
    });
    
    $('a[rel*=ui-button-download]').live('click', function() {
        $.pageTracker._trackPageview($(this).attr('href'));
    });
    
    var showTooltip = function(e) {
        $(this).children().show();
    };
    
    var hideTooltip = function(e) {
        $(this).children().hide();
    };
    
    $('.ui-contextual-help').live('mouseover',showTooltip);
    $('.ui-contextual-help').live('mouseout',hideTooltip);
    
    $('.search-input').each(function() {
    var default_value = this.value;
        $(this).css('color', '#666'); // this could be in the style sheet instead
        $(this).focus(function() {
            if(this.value == default_value) {
                this.value = '';
                $(this).css('color', '#0b1925');
            }
        });
        $(this).blur(function() {
            if(this.value == '') {
                $(this).css('color', '#566d80');
                this.value = default_value;
            }
        });
    });
    
    $('.big_search_input').each(function() {
        var default_value = this.value;
        $(this).css('color', '#666'); // this could be in the style sheet instead
        $(this).focus(function() {
            if(this.value == default_value) {
                this.value = '';
                $(this).css('color', '#0b1925');
            }
        });
        $(this).blur(function() {
            if(this.value == '') {
                $(this).css('color', '#566d80');
                this.value = default_value;
            }
        });
    });
    
});/* ======== /static/js/amie/player.js ======== */

PLAYER_WINDOW_NAME = 'AmiePopoutPlayer';
DETACHED_COOKIE = 'PlayerDetached';
DETACHED_COOKIE_OPTS = { path: '/' };
USE_WINDOW_OPEN_TRICK = ! $.browser.safari;

PlayerBase = function() {};
PlayerBase.prototype = {  
  'in_popout_window': false,


  /**
   * The player is currently setup to have an extremly robust event model.
   * This method is called by the swf to bubble events out to any javascript
   * that happens to be listening.
   * 
   * All events use the player namespace.
   * 
   * Core Events:
   * - player.ready : Dispatched after the swf has fully initialized. data: void
   * 
   * Playing a song:
   * - player.song_start : As soon as a song starts playling.  data: SongVO
   * - player.song_resumed : When play begins after being paused. data: SongVO
   * - player.song_complete : When play has completed for a song.  data: SongVO
   * - player.song_paused : When a song is paused. data: SongVO
   * - player.song_load_start : When loading the mp3 for the song begins.  data: SongVO
   * - player.song_load_complete : When the mp3 has completed loading into the buffer. data: SongVO
   * 
   * Playlist Events:
   * - player.playlist_complete : When the player has completed the last item in the playlist and repeat is set to none. data: void
   * - player.playlist_album_added : When an album has been added to the playlist. data: AlbumVO
   * - player.playlist_song_added : When an album has been added to the playlist. data: SongVO
   * 
   * @access Private
   * @return Void
   */
  'broadcastEvent': function(name, data, srcWindow) {
      if (! srcWindow) {
        srcWindow = window;
      }
      $.log('broadcasting event: ' + name);
      switch(name){
          case 'song_start':
              $(document).trigger('player.song_start', [data]);
              $(document).trigger('player.visible', [data]);
          break;
          case 'ready':
              $.log('player ready');
              $.player.loaded(srcWindow);
              $(document).trigger('player.ready', [data]);
          break;
          default:
              $(document).trigger('player.' + name, [data]);
          break;
      }
  },

  /////////////////////////////
  // Access to the SWF from JS and access to JS from the SWF
  /////////////////////////////	
  /**
   * Gets a dom reference to the swf which has all methods exposed via its External Interface.
   * 
   * @access Private
   * @return Object A dom reference to the swf.
   */
  'getSwfFromDom': function(win) {
      $.log('getting swf object');
      var movieName='RazrPlayer';
      if (win.document[movieName]) {
        return win.document[movieName];
      } else if ((navigator.appName.indexOf("Microsoft Internet") == -1) &&
          (win.document.embeds && win.document.embeds[movieName])) {
        return win.document.embeds[movieName];
      } else {
        return win.$('#' + movieName).get(0); // may be undefined
      }
  },

	'openPage': function(url, useHistoryManager){
    if(useHistoryManager){
      $.history_manager.loadUrl(url);
    }
    else{
      document.location = url;
    }
	},

  'shouldPersistentPlay': function() {
    return false;
  }

};


/**
 * Called on PlayerBase.prototype in the popup window which changes event broadcasting
 * to be forwarded to the opener
 */
if (window.name == PLAYER_WINDOW_NAME) {
  
  $.extend(PlayerBase.prototype, {
    'in_popout_window': true,

    'broadcastEvent': function(name, data) {
      if (opener == window) {
        $.log('opener is self! no good!');
        return;
      }
      $.log("Forwarding event: " + [name, data]);
      opener.$.player.broadcastEvent(name, data, window);
    },

    'openPage': function(url, useHistoryManager) {
      if (window.opener && !window.opener.closed){
        window.opener.document.location = url;
        window.opener.focus();
      }
      else{
        window.open(url);
      }
    }
  });
}


LoadingPlayer = function() {};
LoadingPlayer.prototype = $.extend(new PlayerBase(), {
  'queue': [],

  'getLoadedType': function() {
    return false;
  },

  'getLoadedCollectionId': function() {
    return false;
  },

  'getCurrentSong': function() {
    return false;
  },
  
  'isVisible': function() {
    return false;
  },

  'hide': function() { },

  'loaded': function(targetWindow) {
    if (! targetWindow) {
      targetWindow = window;
    }

    $.log('LoadingPlayer.loaded in ' + targetWindow);
    var swf = this.getSwfFromDom(targetWindow);
    $.log('LoadingPlayer got swf: ' + swf + ", queue is " + this.queue);
    $.player = new Player(swf);
    var call;
    var idx;
    $(this.queue).each(function(idx) {
      var call = this;
      $.log('calling #' + idx + ': ' + call[0]);
      $.player[call[0]].apply($.player, call[1]);
      $.log('call done');
    });
  },

  'badFlash': function() {
    $.player = new BadPlayer();
  },

  'getCurrentState': function() {
    return '';
  }
});

// Since IE doesn't support __noSuchMethod__ we manually register any functions that
// have to delay invocation until the player is loaded.
$(['playSong', 'playCollection',  'popoutWin', 'show', 'playOrPause', 'nextTrack','prevTrack',
   'setHasPopout']).each(function() {
  var funcName = this;
  LoadingPlayer.prototype[funcName] = function() {
    $.log("loading player delaying invocation of " + funcName);
    this.queue.push([funcName, arguments]);
  };
});

WaitingForPopoutPlayer = function() {};
WaitingForPopoutPlayer.prototype = $.extend(new LoadingPlayer(), {
  'waitingForPopout': true,
  'contactTimeout': 0,

  'loaded': function(targetWindow, force) {
    if (!force && targetWindow == window) {
      $.log("Internal SWF has loaded but we're waiting for a popup window.");
      var self = this;
      this.contactTimeout = setTimeout(function() {
        $.log("We never got contacted by popout. clearing cookie and loading internal");
        $.log("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% REMOVING COOKING");
        $.cookie(DETACHED_COOKIE, null, DETACHED_COOKIE_OPTS);
        self.loaded(targetWindow, true);
      }, 3000);
    } else {
      if (! force) { $.log("Main window got contacted by player window."); }
      if (this.contactTimeout) { clearTimeout(this.contactTimeout); }
      this.setHasPopout(! force);
      return LoadingPlayer.prototype.loaded.apply(this, [targetWindow]);
    }
  }
});

///////////////////////////////////////////////////////////
// Player class - loaded into $.player once the SWF is successfully loaded
////////////////////////////////////////////////////////////
Player = function(swf) {
  this.swf = swf;
};
Player.prototype = $.extend(new PlayerBase(),
{
  /**
   * true if this is the main window player instance that is wrapping
   * a swf on an external page
   */
  'hasPopout': false,

  'getSwf': function() {
    return this.swf;
  },

  /**
   * Tell the player to hide itself if its not already visible.
   * @access Public
   * @return Void
   */
  'hide': function() {
    if(!this.swf.getVisibility()) {
      return; //already hidden
    }
    $('#player-box-wrapper').addClass('player-hidden');
    this.swf.setVisibility(false);
    $('body').removeClass('playing');
    if($(document).data('isIe6')){
       $('#player-box-wrapper').css({position: 'relative'});
    }
  },

  /**
	 * Tell the player to show its yellow belly....
	 * 
	 * Will automatically resize the parent container before the SWF animation starts. 
	 * @access Public
	 * @return Void
	 */
	'show': function() {
    if (this.swf.getVisibility()) {
      return; // already visible
    }
    $('#player-box-wrapper').removeClass('player-hidden');
    $('body').addClass('playing');
    if($(document).data('isIe6')){
      $('#player-box-wrapper').css({position: 'absolute', bottom: 0});
      var o =(parseInt(($(window).height() + $(window).scrollTop()))-70);
      if(o < $('body').height()){
        $('#player-box-wrapper').css({top: o+'px'});
      }
    }
    this.swf.setVisibility(true);
  },
  
  'isVisible': function() {
    return this.swf.getVisibility();
	},

  'shouldPersistentPlay': function() {
    return this.isVisible() && !this.hasPopout;
  },

  'setHasPopout': function(val) {
    this.hasPopout = val;
    return this;
  },

  'hasBadFlash': function() { return false; },

  /**
	 * Play a song immediately.
	 * 
	 * If the player is currently playing this song, this will pause it.
	 * 
	 * If the player is not ready yet, it will add a listener for the player.ready
	 * event which will then play it.
	 * 
	 * @param int id The song id to play.
	 * start playing or clear the playlist (false) and start playing the song.
	 * @access Public
	 * @return Void
	 */
  'playSong': function(id){
    if(!id){
      var id = arguments.data[0];
    }
    this.show();
    this.swf.playSong(id);
  },
	
  /**
   * Play a collection of songs - right now either playlist or album.
   * 
   * @param type String The type of collection, right now either 'playlist' or 'album'.
   * @param id String The encrypted ID of the collection.
   * @param startSongId String The encrypted ID of the song to start with.
   * @access Public
   * @return Void
   */
  'playCollection': function(type, id, startSongId) {
    if(!type && !id && !startSongId){
      var type = arguments.data[0];
      var id = arguments.data[1];
      var startSongId = arguments.data[2];
    }
    this.show();
    $.player.lastSeenCollectionType = type;
    $.player.lastSeenCollectionId = id;
    this.swf.playCollection(type, id, startSongId);
  },

  'openPopout': function() {
    try {
      var opts = 'status=no,toolbar=no,resizable=yes,location=no,menubar=no,directories=no,scrollbars=no,height=350,width=468';
      var url = '/player/popout';
      $.log('popout!');
      this.popoutWin = window.open(url, PLAYER_WINDOW_NAME, opts);
      if(!this.popoutWin){
        $.log('POPOUT BLOCKED!');
        $.pageTracker._trackEvent('listen', 'open popout blocked', 'bottom player');
        throw('blocked');
      }
      else{
        $.log('POPUP SUCCESSFUL');
        $.player = new LoadingPlayer(this.popoutWin);
        $.cookie(DETACHED_COOKIE, 1, DETACHED_COOKIE_OPTS);
        $.log('cookie is: ' + $.cookie(DETACHED_COOKIE));
        $.player.setHasPopout(true);
        // This gets queued up in LoadingPlayer until the popout has surfaced
        if (this.getLoadedType() == 'single') {
            $.log('queueing playsong!');
            $.player.playSong(this.getCurrentSong().id);
        } else {
            $.log('queueing play collection!');
            $.player.playCollection(this.getLoadedType(), this.getLoadedCollectionId(), this.getCurrentSong().id);
        }
        $.pageTracker._trackEvent('listen', 'open popout success', 'bottom player');
      }
    }
    catch(e){
      $.log('CAUGHT EXCEPTION: ' + e);
      $.uiLightbox('<div style="padding: 20px; background-color: white;"><h1>Popup Blocked</h1><p>If seems that your browser blocked the popup for the popout player.</p><p>To access the popout player please <a href="'+url+'" rel="no-history" onclick="$.player.playOrPause();$.player.hide();$.unblockUI();window.open(url, PLAYER_WINDOW_NAME, opts); event.preventDefault(); event.stopPropogation(); return false;" target="_blank">click here</a>.</p><div class="footer"><a href="javascript: void(0);" onclick="$.unblockUI();" class="close"><img src="/static/acf/ui-lightbox/closelabel.gif" alt="Close Lightbox" class="close_image" /></a></div></div>');
      $.pageTracker._trackEvent('listen', 'open popout showed blocked message', 'bottom player');
      return;
    }
    this.closePlayer();
  },

  /**
   * Called when the popout window is closed
   */
  'popoutClosed': function(mainWindow) {
    $.log("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% REMOVING COOKIE");
    $.cookie(DETACHED_COOKIE, null, DETACHED_COOKIE_OPTS);
    mainWindow.$.log('Popout closed! unset cookie');
    mainWindow.$.player = new Player(this.getSwfFromDom(mainWindow));
    // Popped out player is playing, so load the same song in the
    // bottom player
    if (this.getCurrentState() == 'PLAYING') {
      // TODO(atm) there's no external interface call to just load a song
      // and not play it, but we'd rather do that here, evidently. (#2855)
      mainWindow.$.player.playCollection(this.getLoadedType(), this.getLoadedCollectionId(), this.getCurrentSong().id);
      mainWindow.$.player.playOrPause();
    }
  },

  'closePlayer': function() {
    if (this.getCurrentState() == 'PLAYING') {
      this.playOrPause();
    }
    this.hide();
  },
  'getMoreInfoDiv': function(){
      return $('#player-now-playing-info');
  },
  'toggleMoreInfo': function(){
      var playerMoreInfo = $.player.getMoreInfoDiv();
      if (playerMoreInfo.hasClass('hide')) {
          return $.player.showMoreInfo();
      } 
      else {
          return $.player.hideMoreInfo();
      }
  },
  'showMoreInfo':function(){
      var playerMoreInfo = $.player.getMoreInfoDiv();
      //playerMoreInfo.removeClass('hide');
      //playerMoreInfo.animate({ height: '140px' }, 250);
      playerMoreInfo.fadeIn();
      playerMoreInfo.removeClass('hide');
      
      return false;
  },
  'hideMoreInfo':function(){
      var playerMoreInfo = $.player.getMoreInfoDiv();
      playerMoreInfo.fadeOut();
      playerMoreInfo.addClass('hide');
      return false;
  },

  
  /////////////////////////////
  // Playlist Controls
  /////////////////////////////
  /**
   * Play or pause the current song loaded in the player.
   * @access Public
   * @return player.state
   */
  'playOrPause': function() {
    this.getSwf().playOrPause();
    return this.getCurrentState();
  },

  'closePlayer': function() {
    if(this.getCurrentState() == 'PLAYING') {
        this.playOrPause();
    }
    this.hide();
  },
  'playEmbeddedCollection' : function(type, id, selector){
      this.show();
      if(type!=$.player.lastSeenCollectionType && id!=$.player.lastSeenCollectionId){
          $(selector).each(function(i){
              var id = $(this).attr('class').match(/(?:song-)[\w.-]{11}x/)[0].replace('song-', '');
              if(i==0){
                  $.player.playSong(id);
              }
              else{
                  $.player.addSong(id);
              }
          });
          $.player.lastSeenCollectionType = type;
          $.player.lastSeenCollectionId = id;
      }
      else{
          this.playOrPause();
      }
  }
});
$(['nextTrack','hasNextTrack','hasPrevTrack','prevTrack', 'getLoadedType',
   'getLoadedCollectionId','getCurrentState', 'getCurrentSong', 'getCurrentIndex', 'addSong']).each(function() {
  var f = this;
  Player.prototype[f] = function() {
      // This is the worst code I have ever written in my entire life,
      // but some browsers don't seem to allow you to call .apply on functions
      // inside swf objects
      if (arguments.length === 0) {
          return this.swf[f]();
      } else if (arguments.length == 1) {
          return this.swf[f](arguments[0]);
      } else if (arguments.length == 2) {
          return this.swf[f](arguments[0], arguments[1]);
      } else {
          alert('unexpected argument length on swf call');
          return this.swf[f].apply(this.swf, arguments);
      }
  };
});

////////////////////////////////////////////////////////////
// BadPlayer class - loaded into $.player when flash is detected as bad.
// This happens when the amie.bad_flash event is triggered by AS_Swf
////////////////////////////////////////////////////////////

BadPlayer = function() {};
BadPlayer.prototype = {
  'hide': function() {
    $('#player-box').css('height', '1px');
  },
  'show': function() {
    this.resizeForBadFlash();
  },

  'hasBadFlash': function() { return true; },

  'isVisible': function() { return false; },

  'resizeForBadFlash': function() {
    $('#player-box-wrapper').removeClass('player-hidden');
    $('#player-box, #player-box > div, #player-box > div > div').css('height', '75px').show();
    $(document).data('badFlash', true);
  }
};

$(['getCurrentState','getCurrentSong','getLoadedCollectionId', 'getLoadedType']).each(function() {
  BadPlayer.prototype[this] = function() { return undefined; };
});
$(['playSong','playCollection','nextTrack','prevTrack','addSong']).each(function() {
  BadPlayer.prototype[this] = function() { this.resizeForBadFlash(); };
});

////////////////////////////////////////////////////////////////////////////////

// The player starts out in the Loading state
// However, if there's a cookie that says the player has been detached, we want
// to hunt down that window
$.player = (function() {
  $.log("getting player");
  if ((window.name != PLAYER_WINDOW_NAME) && $.cookie(DETACHED_COOKIE)) {
    if (USE_WINDOW_OPEN_TRICK) {
      /**
       * This nice trick allows us to grab a reference to the popout window without
       * making it navigate anywhere. Sadly, though, Safari will pop the popout window
       * to the front when we use this trick, so we have to rely on the popout window
       * finding us and calling us back after we reload.
       */    
      $.log('USING WINDOW_OPEN_TRICK!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!');
      var pop = window.open('', PLAYER_WINDOW_NAME);
      if (pop.$) {
        // the popup window we found has a jquery object, which means it's a valid popout
        // player
        $.log('detached player seems valid');
        return new Player(PlayerBase.prototype.getSwfFromDom(pop)).setHasPopout(true);
      } else {
        $.log('detached player was broke (no $!) so cleaning up');
        // no jquery in popup. This means that our cookie was mistaken and we've just
        // opened a blank browser window. So, we close that blank window that we just opened.
        // This is ugly since the window bounces into appearance and disappears, but only
        // happens if our cookie was mistakenly set.
        try { pop.close(); } catch (e) {}
        $.log("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% REMOVING COOKING");
        $.cookie(DETACHED_COOKIE, null, DETACHED_COOKIE_OPTS);
      }
    } else {
     $.log('Not using WINDOW_OPEN_TRICK - waiting for popout player to contact us');
     // We can't use the window.open trick to regain control of our popout player
     // on certain browsers since it will cause the popout to jump to the front
     // on every main-window page load. Instead we go to a WaitingForPopoutPlayer
     // state
      return new WaitingForPopoutPlayer();
    }
  }
  $.log('no detached player, loading player on page');
  return new LoadingPlayer();
})();

$(document).bind('amie.bad_flash', function() {
  $.log('amie.badflash');
  $.player.badFlash();
});


$(document).ready(function() {
  /**
	 * When the player has completed its hide effect, set the height of 
	 * the container to 1px so it doesnt get in the way.
	 */
	$(document).bind('player.hidden', function(){
      removeHighlights();
      removeSongPaused();
  });

	/**
	 * Just a marker back into JS for doing an easy check/toggle.
	 */
	$(document).bind('player.visible', function(){
      $.player.show();
  });
  $(document).bind('player.song_start', function(event, data){
      $.player.lastSeenSong = data.song;
      $('#player-now-playing-info .player-more-info').load('/player/now-playing-bottom-album?songId=' + data.song.id);
  });
  $(document).bind('player.playlist_complete', function(){
      $.player.hideMoreInfo();
      $.player.closePlayer();
      if(!$.player.in_popout_window && $.player.lastSeenCollectionType=='album'){
          window.openLightbox('/player/playlist-complete?songId='+$.player.lastSeenSong.id, 'close-on-click');
      }
  });
  $(document).bind('player.song_complete', songComplete);
  $(document).bind('player.song_start', function(event, data) {
      removeSongPaused();
      highlightNowPlaying(event, data);
  });
  $(document).bind('player.song_paused',songPaused);
  $(document).bind('player.song_resumed',songResumed);
  $(document).bind('amie.ready', function() {
      $.log('amie.ready');
      removeHighlights();
      removeSongPaused();
      var currentSong = $.player.getCurrentSong();
      if(currentSong) {
          addHighlights(currentSong);
          if($.player.getCurrentState() == 'PAUSED') {
              addSongPaused(currentSong);
          }
      }
  });

  $('#bottom-player-close-button').click(function(){
  	  $.pageTracker._trackEvent('listen', 'bottom player', 'close clicked');
  });
  $('#bottom-player-detach-button').click(function(){
  	  $.pageTracker._trackEvent('listen', 'bottom player', 'open popout clicked');
  });
 
  function removeHighlights() {
      $('.highlight-item-playing').removeClass('highlight-item-playing');
  }

  function addHighlights(song) {
      $('.song-' + song.id).addClass('highlight-item-playing');
      $(getCollectionClass()).addClass('highlight-item-playing');
  }

  function highlightNowPlaying(event, data) {
      removeHighlights();
      addHighlights(data.song);
  }

  function addSongPaused(song) {
    $('.song-' + song.id).addClass('song-paused');
    $(getCollectionClass()).addClass('song-paused');
  }
  
  function songPaused(event, data) {
    addSongPaused(data.song);
  }

  function removeSongPaused() {
    $('.song-paused').removeClass('song-paused');
  }
  
  function songResumed(event, data) {
    addHighlights(data.song);
    removeSongPaused();
  }

  function songComplete(event, data) {
    removeHighlights();
    removeSongPaused();
  }

  function getCollectionClass() {
    return '.' + $.player.getLoadedType() + '-' + $.player.getLoadedCollectionId();
  }
});
/* ======== /static/js/amie/util.js ======== */

/**
 * Always include this file after amie/main.js.
 */
window.Amie.Util = {};
var Util = Amie.Util;

Util.ajaxifyCheckbox = function(id, url, success_fn) {
    if (!success_fn)
        success_fn = function () {};

    $("#" + id).bind('click', function(e, ui) {
        var checked = $("#" + id + ":checked").val() ? 1 : 0;
        $.post(url, { 'checked' : checked }, success_fn);
    });
};

Util.observep = function(atag, p) {
    atag.href = Util.getObservepUrl(atag.href, p);
    return true;
};

Util.getObservepUrl = function(href, p) {
    return (href + "&dp=" + p);
};
Util.isOsx = function(){
    return (navigator.userAgent.toLowerCase().indexOf("mac")!=-1);
};
Util.isWindows = function(){
    return (navigator.userAgent.toLowerCase().indexOf("windows")!=-1);
};