if (!Fair && top.Fair){
  top.Fair.Content = window;
  var Fair = top.Fair;
} else if (!Fair) Fair = {};
var Local = {};

//Common Scripts for all content pages
Fair.Common = {};

//Link behaviors by type
Fair.Common.Links = {
  
  download: function(link){
    var action = link.hasClass('external') ?
      function(event){ Fair.Common.Overlay.show('external', link.href, 'track'); event.stop(); } :
      function(event){
        if (link.hasClass('downloaded')){ event.stop(); return; }
        link.addClass('downloaded').set('text', 'downloaded');
        Fair.Roar.alert('Your track is being downloaded...');
      };
    link.addEvent('click', action);
  },
  
  permalink: function(link){
    var input = link.getParent().getNext().getFirst().addEvents({
      blur: function(){ this.slide('out'); },
      click: function(){ this.select(); },
      mousedown: function(){ this.select(); }
    }).set('slide', { 'mode': 'horizontal', duration: 300 }).slide('hide');
    link.addEvent('click', function(event){
      input.select();
      input.slide();
      event.stop();
    });
  },
  
  play: function(link){
    var type = link.className.split(' ')[0];
    link.addEvent('click', function(event){
      event.stop();
      var feed = link.get('href'), empty = feed == '#',
          id = type == 'track' ? this.id.parseId() : 0;
      if (link.hasClass('pause')) Fair.Player.fairpause();
      else {
        link.className = 'loading button';
        if (!Fair.Session && empty) feed = '/track/' + id + '.xspf';
        Fair.Player.fairplay(id, empty ? Fair.Params.feed : feed);
      }
    });
  },
  
  show: function(link){
    var persist = link.hasClass('persistent'),
        description = link.getParent().getNext(),
        slide = description.get('slide', { transition: 'quad:out' }).hide();
    
    if (!persist){
      var snippet = description.getElement('div.content');
      snippet = (snippet ? snippet.getElement('p').clone() : new Element('p')).inject(link, 'after');
    }
    
    link.getParent().addEvent('click', function(event){
      var target = $(event.target);
      if (target.get('tag') == 'a' && target != link) return;
      var visible = slide.open;
      link[visible ? 'removeClass' : 'addClass']('active');
      if (snippet) snippet.fade(visible ? 'in' : 'out');
      slide.start(visible ? 'out' : 'in');
      event.stop();
    });
  },
  
  vote: function(link, model){
    var id = link.id.parseId().toInt(),
        owned = Fair.Session[model + 's'];
    
    if (owned && owned.contains(id)){ this.cantvote(link, model); return; }
    link.addEvent('click', function(event){
      event.stop();
      Fair.Common.Votes.vote(model, id);
    });
  },
  
  cantvote: function(link, model){
    link.addEvent('click', function(event){ event.stop(); }).set({
      'class': model + ' cantvote button',
      'title': "You can't vote for your own " + model + "!"
    });
  }
  
};

//restricted actions
['cantadd', 'cantplay', 'cantshare'].each(function(key){
  Fair.Common.Links[key] = function(link){
    link.addEvent('click', function(event){
      event.stop();
    });
  };
});

//overlay actions
['abuse', 'add', 'feedback', 'groups', 'inbox', 'invite', 'overlay', 'password', 'reassign', 'reject', 'share', 'stats'].each(function(key){
  var Key = key.capitalize();
  Fair.Common.Links[key] = function(link, model){
    if (!link) return;
    link.addEvent('click', function(event){
      event.stop();
      Fair.Common.Overlay.show(key, link.href, model);
    });
  };
});

Fair.Common.Owner = {
  
  sync: function(model){
    var owned = Fair.Session[model + 's'];
    
    if (!owned || !owned.length) return;
    owned.each(function(item){
      // Enable adding owners private tracks to playlists
      var trackAddButton = $('track_add_button_' + item);
      if (trackAddButton){
        if (trackAddButton.hasClass('cantadd') && trackAddButton.hasClass('private')) {
          trackAddButton.replaceClass('cantadd', 'add');
        }
      }
    });
  }
};

//show edit buttons and admin links in lists
Fair.Common.Admin = {
  
  sync: function(model){
    var owned = Fair.Session[model + 's'],
        admin = Fair.Session.level == 'admin';
    
    if (!owned || !owned.length) return;
    $$('table.track').each(function(item){
      if (admin || owned.contains(item.id.parseId().toInt())){
        var links = $(item.id + '_admin_links');
        if (links) links.show();
      }
    });
  },
  
  update: function(){
    var inbox = $('inbox_count'),
        inbox_count = Fair.Session.inbox_count;
        
    if (inbox){
      if (inbox_count) inbox.set('html', '(' + inbox_count + ')').show();
      else if (inbox_count == 0) inbox.hide(true).set('html', '(0)');
    }
  }
  
};

//Actions for Inviting
Fair.Common.Invite = {
  
  send: function(emails, message){
    var params = { emails: emails };
    if (message) params['message'] = message;
    this.Request.post(params);
  }
  
};

//Show any type of overlay
Fair.Common.Overlay = {
  
  show: function(type){
    if (type == 'overlay') this[type] = new Overlay({ destroy: true, jumpToTop: true });
    if (!this[type]) this[type] = new Overlay[type.capitalize()]();
    this[type].overlay.apply(this[type], Array.slice(arguments, 1));
  }
  
};

//Play behavior for syncronizing all feed and track play buttons
Fair.Common.Plays = {
  
  sync: function(feed_url, track_id, playing){
    var player = Fair.Player;
    if (!player.current_feed) return;
    if (!feed_url) feed_url = player.current_feed();
    if (!track_id) track_id = player.current_track_id();
    if (!playing)  playing  = player.fairplaying();
    
    ['track', 'playlist', 'user', 'radio'].each(function(model){
      var module = Fair[model.capitalize() + 's'];
      if (!module || !module.playButtons) return;
      var text = (model == 'user' ? "member's music" : model);
      module.playButtons.set({'class': model + " play button", 'title': 'Play this ' + text});
    });
    
    var string = feed_url && feed_url.match;
    var radio = string && feed_url.match('button_id');
    var model = string && feed_url.match('playlist|user|radio');
    
    if (model){
      model = model[0];
      var module = Fair[model.capitalize() + 's'],
          text = (model == 'user' ? "member's music" : model),
          button = radio ? $(feed_url.match(/button_id=(radio_\w+)/)[1]) : $(model + '_play_button_' + feed_url.parseId());
      if (button){
        if (playing) button.set({'class': model + ' pause button', 'title': 'Pause this ' + text});
        else button.set({'class': model + ' paused button'});
      }
    }
    
    if (track_id){
      button = $$('[id=track_play_button_' + track_id + ']');
      if (button){
        if (playing) button.set({'class': 'track pause button', 'title': 'Pause this track'});
        else button.set({'class': 'track paused button'});
      }
    }
  }
  
};

//A common image uploader
Fair.Common.Uploader = {
  
  init: function(model, id){
    var image = $('main_picture');
    if (!image) return;
    
    var uploader, that = this,
        adjust = $('picture_adjust_button'),
        browse = $('picture_browse_button'),
        message = 'There was a problem uploading the image',
        reset = function(){ image.fade('in'); Fair.Roar.alert(message); };
    
    image.addEvent('load', function(){
      var field = image.getParent();
      if (field.hasClass('fieldWithErrors')){ field.getFirst().inject(field, 'before'); field.destroy(); }
      adjust.show();
      image.fade('in');
    });

    if (browse) browse.addEvent('click', $lambda(false));
    if (adjust) adjust.addEvent('click', function(event){
      event.stop();
      var href = '/pictures/cropper?record_id=' + id + '&record_type=' + model.capitalize();
      Fair.Common.Overlay.show('cropper', href);
    });
    
    var container = new Element('div').setStyles({
      width: '100%',
      height: '14px',
      overflow: 'hidden',
      position: 'relative'
    }).replaces(browse);

    uploader = new Swiff.Uploader({
      data: Fair.Session ? {_session_id: Fair.Session.session_id} : {email: $('user_email').value},
      method: 'POST',
      multiple: false,
      fieldName: 'picture',
      container: container,
      path: '/flash/Swiff.Uploader.swf',
      url: '/' + model + 's/picture/' + id + '?format=json',
      typeFilter: {'Images (*.jpg, *.jpeg, *.gif, *.png)': '*.jpg; *.jpeg; *.gif; *.png'},
      callBacks: {
        onError: reset,
        onAllSelect: function(){ image.fade(0.2); uploader.upload(); },
        onComplete: function(file, response){
          var json = $H(JSON.decode(response, true)), source = json.src + '?' + $time();
          if (json.get('result') != 'success') reset();
          else image.removeClass('default').get('tween').start('opacity', 0).chain(function(){ image.src = source; });
          var cropper = $('image_cropper');
          if (cropper) cropper.destroy();
          that.sync(model, id, source);
        }
      }
    });
    
    container.adopt(browse);
  },
  
  sync: function(model, id, source){
    if (model == 'user' && Fair.Session && Fair.Session.id == id) $('user_avatar').src = source;
  }

};

Fair.Common.Create = {
  
  countryAutocompleter: function(field){
    new Autocompleter.Local(field, Fair.Countries, {
      minLength: 1,
      className: 'country menu',
      filter: function(){
        var query = this.queryValue,
            escaped = query.escapeRegExp(),
            regex = new RegExp('^' + escaped, 'i'),
            regex2 = new RegExp('^' + escaped + '| ' + escaped, 'i'),
            iso = this.tokens.filter(function(token){ return query.length == 2 && regex.test(token[1]); }),
            name = this.tokens.filter(function(token){ return !iso.contains(token) && regex2.test(token[0]); });
        return iso.concat(name);
      },
      injectChoice: function(choice){
        var code = new Element('span', {'class': 'code'}).set('html', this.markQueryValue(choice[1]));
        var el = new Element('li').set('html', this.markQueryValue(choice[0])).setStyle('background-image', 'url(/images/flags/' + choice[1].toLowerCase() + '.gif)');
        code.inject(el, 'top');
        el.inputValue = choice[0];
        this.addChoiceEvents(el).inject(this.choices);
      }
    });
  },
  
  namedAutocompleter: function(controller, model){
    var input = $(controller + '_' + model + '_name'), url = '/autocomplete?model=' + model;
    if (!input) return;
    new Autocompleter.Request.HTML(input, url, {
      delay: 100,
      postVar: 'value',
      onRequest: function(){ input.addClass('loading'); },
      onFailure: function(){ input.removeClass('loading'); },
      onComplete: function(){ input.removeClass('loading'); }
    });
  }

};

//Default Voting behavior
Fair.Common.Votes = {
  
  sync: function(model){
    Fair[model.capitalize() + 's'].voteButtons.set({'class': model + ' vote button', 'title': 'Vote for this ' + model});
    Fair.Session[model + '_votes'].each(function(id){
      var button = $(model + '_vote_button_' + id);
      if (button) button.set({'class': model + ' fanof button', 'title': 'Withdraw your vote'});
    });
  },
  
  vote: function(model, id){
    if (!id) return;
    else if (!Fair.Session){ alert('Login to vote!'); return; }
    else if (!this.Requests[model][id]) this.Requests[model][id] = new Request.JSON({
      link: 'cancel',
      onSuccess: this.respond.bind(this)
    });
    this.request(model, id, !Fair.Session[model + '_votes'].contains(id.toInt()));
  },
  
  request: function(model, id, state){
    var url = (model == 'track' ? '' : model + '_') + 'votes', timeframe = '';
    this.update(model, id, state, '<img src="/images/spinner.gif" alt="loading" />');

    var vote_button = $(model + '_vote_button_' + id);
    if (vote_button) timeframe = '?' + vote_button.href.split('?')[1];
    
    this.Requests[model][id].post('/' + url + '/' + (state ? 'create' : 'destroy') + '/' + id + timeframe);
  },
  
  respond: function(response){
    this.update(response.model, response.id, response.state, response.count);
  },
  
  update: function(model, id, state, count){
    Fair.Session[model+'_votes'][state ? 'include' : 'erase'](id.toInt());
    var vote_count = $(model + "_vote_count_" + id), vote_button = $(model + "_vote_button_" + id);
    if (vote_count) vote_count.set('html', count);
    if (vote_button) vote_button.set({
      'class': (model + ' ' + (state ? 'fanof' : 'vote') + ' button'),
      'title': (state ? 'Withdraw your vote' : 'Vote for this ' + model)
    });
    // Update vote info on player V2 (V3 is backward-compatible)
    if (model == 'track' && id == Fair.Player.current_track_id()) Fair.Player['switch_to_' + (state ? 'unvote' : 'vote')]();
    // Update vote info on player V3, enabled now that V2 is forward-compatible
    Fair.Player[model + (state ? '_voted' : '_unvoted')](id);
  }
  
};

//Common Initialization
Fair.Common.init = function(){
  if (window.Roar) Fair.Roar = new Roar({ container: $('container') });
  Fair.Scroller = new Fx.Scroll(document.body, { offset: { y: -20 } });
  
  //radios don't have their own js module yet as the only place we have buttons for them is on the home page
  var buttons = $$('a.radio.play.button');
  buttons.each(function(button){ Fair.Common.Links.play(button); });
  Fair.Radios = { playButtons: buttons };
  
  this.Votes.Requests = { track: {}, playlist: {} };
  this.Invite.Request = new Request.JSON({ url: '/invites/create' });
  
  if (Fair.Messages){
    var input = $('search-text'), clear = false;
    if (input){
      if (Fair.Messages.controller == 'users') Fair.Messages.controller = 'community';
      if (!Fair.Messages.search){
        clear = true;
        Fair.Messages.search = 'Search in ' + Fair.Messages.controller;
      }
      else input.addClass('active');
      input.addEvents({
        blur: function(){ if (clear && this.value.clean() == '') this.value = Fair.Messages.search; },
        focus: function(){ if (clear && this.value == Fair.Messages.search) this.value = ''; }
      }).value = Fair.Messages.search;
      
      $('search-submit').addEvent('click', function(event){
        event.stop();
        if (!Fair.Session || input.value == Fair.Messages.search) return;
        this.getParent().submit();
      });
    }
    
    if (Fair.Roar && Fair.Messages.flash) Fair.Roar.alert(Fair.Messages.flash);
  }
  
  $$('div.tab-container').each(function(container){
    new TabContainer(container, {
      initialize: function(){
        this.tabs.each(function(tab, index){
          var feed = tab.get('href');
          if (!feed || !feed.match('.xspf')) return;
          if (Fair.Player && Fair.Player.preload_feed) Fair.Player.preload_feed(feed);
          this.panes[index].getElements('a.track.play.button').set('href', feed);
        }.bind(this));
      }
    });
  });
  
  $$('[feed]').each(function(container){
    container.getElements('a.track.play.button').set('href', container.get('feed'));
  });
  
  $$('div.features a.track.play.button', 'table.explore a.track.play.button').each(function(link){
    if (link.get('href') == '#') link.href = '/track/' + link.id.parseId() + '.xspf';
  });

  $$('a.download, a.feedback, a.inbox, a.overlay, a.password, a.permalink, a.show').each(function(link){
    this.Links[link.className.split(' ')[0]](link);
  }, this);
  
  if (Fair.Session && Fair.Fixed) this.Admin.update();
};

window.addEvents({
  domready: Fair.Common.init.bind(Fair.Common),
  load: function(){
    if (!Fair.Tracks || !Fair.Playlists) return;
    else if (Fair.Tracks.loaded && Fair.Playlists.loaded && Fair.Users.loaded){
      if (Fair.Player) Fair.Common.Plays.sync();
    } else arguments.callee.delay(50);
  }
});

function ShowFlashMessage(title, message){
  if (Fair.Roar) Fair.Roar.alert(title, message || '');
}

//magic
Request.JSON.implement({
  onSuccess: function(response){
    if (response){
      var message = response.alert || response.notice || response.flash,
          errors = response.errors;
      if (Fair.Roar && message) Fair.Roar.alert(message);
    }
    this.parent.apply(this, arguments);
  }
});

