/**
 * Javascript Site RVCQ
 * Turbulent Media - janvier 2010
 * @author frederic GINIOUX
 */

jQuery.fn.extend({
  hitch: function(ev, fn, scope) 
  {
    return this.bind(ev, function() 
    {
     return fn.apply(scope || this, Array.prototype.slice.call(arguments));
    });
  }
});

/**
 * Namespace rvcq pour le javascript du site
 */
var rvcq = rvcq || {};

rvcq.tools = {};
rvcq.tools.stopEvent = function(evt){
	if(window.event){ //IE
		evt = window.event;
		evt.returnValue = false;
	}
	try {
		evt.cancelBubble = true;
		if(evt.preventDefault) evt.preventDefault();
		if(evt.stopPropagation) evt.stopPropagation();
		if(evt.stopped) evt.stopped = true;
	} catch(e) {
		/* console.log(e.message); */
	}		
	return evt;
};

rvcq.error = function(msg) {
  alert(msg);
};

rvcq.translate = function(token) {
  if (token.match(/\s/)) return token;
  return heap.translate(token);
}
 
/**
 * Caroussel Widget
 */
rvcq.Caroussel = function(container, options){
 	this.defaultOptions = {duration: 500, easing: 'easeOutCubic', speed: 'slow', display: 3, itemCssClass: '', scrollerCssClass: ''};
	this.options = jQuery.extend({}, this.defaultOptions, options);
	this.container = $(container);
	this.scroller = new Object();
	this.items = new Array();
	this.btns = jQuery('.btn', this.container);
	this.index = 0;
	this.isInProcess = false;
	return this.initialize();	
};
 
$.extend(rvcq.Caroussel.prototype, {
 	/**
 	 * Initialise l'instance de l'objet 
 	 * Recupere tous les éléments et les enregistre dans le tableau this.items
 	 * Initialise l'objet scroller du caroussel
 	 * Enregistre les gestionnaires d'évènements sur les boutons de défilement
 	 * @return {Object} l'instance courante
 	 */
	initialize: function(){
		$(this.options.itemCssClass, this.container).each(function(i, elt){
			this.items.push(new rvcq.CarousselElt(elt, {}));
		}.bind(this));
		
		this.initScroller();
		
		this.btns.each(function(i, elt){
			var $btn = jQuery(elt);
			$btn.bindAsEventListener('click', function(e){
				rvcq.tools.stopEvent(e);
				var $btn = arguments[1] || null;
				if(!$btn || $btn.hasClass('.disabled')) return false;
				($btn.hasClass('first'))? this.moveTo('prev') : this.moveTo('next');
				return false;
			}, this, $btn);
		}.bind(this));
		
		return this.setBtnsAvailability();
	},
	
	/**
	 * Déplace le caroussel vers la droite ou la gauche
	 * @param {String} direction : prev || next
	 * @return {Object} l'instance courante
	 */
	moveTo: function(direction){
		if(this.isInProcess) return;
		this.isInProcess = true;
		var distance = (direction == 'prev')? this.getPrev() : this.getNext();
		this.scroller.moveTo(distance, direction);
		return this;
	}, 
	
	/**
	 * Retourne l'index suivant pour un deplacement
	 * @return {Number} valeur de l'index suivant
	 */
	getNext: function(){
		var leftScroll = this.options.display - (this.index+1+this.options.display);
		return this.items[0].getWidth() * leftScroll;
	},
	
	/**
	 * Retourne l'index précédent pour un deplacement
	 * @return {Number} valeur de l'index précédent
	 */
	getPrev: function(){
		var leftScroll = this.options.display - (this.index-1+this.options.display);
		return this.items[0].getWidth() * leftScroll;
	},
	
	/**
	 * Fonction de callback appellée lors d'un déplacement vers l'avant
	 * @return {Object} l'instance courante
	 */
	goNextCallback: function(){
		this.isInProcess = false;
		this.index++;
		return this.setBtnsAvailability();
	},
	
	/**
	 * Fonction de callback appellée lors d'un déplacement vers l'arrière
	 * @return {Object} l'instance courante
	 */
	goPrevCallback: function(){
		this.isInProcess = false;
		this.index--;
		return this.setBtnsAvailability();
	},
	
	/**
	 * Creer une instance de classe rvcq.CarousselScroller
	 * Declare les callback pour les évènements de fin de déplacement
	 * @return {Object} l'instance courante
	 */
	initScroller: function(){
		var params = {length: this.items.length, itemWidth: this.items[0].getWidth(), duration: this.options.duration};
		this.scroller = new rvcq.CarousselScroller($(this.options.scrollerCssClass + ':eq(0)', this.container), params);
		
		$(this.scroller).bind('stopMoveNext', function(e){
			this.goNextCallback();
		}.bind(this)).bind('stopMovePrev', function(e){
			this.goPrevCallback();
		}.bind(this));
		
		return this;
	},	
	
	/**
	 * Vérifie la disponibilité des boutons du caroussel
	 * @return {Object} l'instance courante
	 */
	setBtnsAvailability: function(){
		var $nextBtn = $prevBtn = null;
		this.btns.each(function(i, elt){
			var $btn = $(elt);
			if($btn.hasClass('first')) $prevBtn = $btn;
			else $nextBtn = $btn;
		});
		
		if(this.index <= 0){
			this.index = 0;
			$prevBtn.addClass('disabled');
		} else $prevBtn.removeClass('disabled');
		
		if((this.index+this.options.display) >= this.items.length){
			$nextBtn.addClass('disabled');
		}	else $nextBtn.removeClass('disabled');
		$(this).trigger('endProcess');
		return this;
	}
});
 
/**
	* Caroussel Widget Liste des éléments
  * @param {HTML elt} container : HTML elt.
  * @param {Object} options : objet contenant les options custom de l'élément
  * @methods
  * 	initialize();
  * 	getWidth();
  *		setWidth();
  *		moveTo();
  * @return {Object} l'instance courante
  */
rvcq.CarousselScroller = function(container, options){
 	this.defaultOptions = {duration: 350, easing: 'easeOutCubic', speed: 'slow', length: 0, itemWidth: 400};
	this.options = $.extend({}, this.defaultOptions, options);
	this.container = $(container);
	return this.initialize();
};
 
$.extend(rvcq.CarousselScroller.prototype, {
 	initialize: function(){
		return this.setWidth();
	},
	
	/**
	 * Ajuste la taille du container des éléments
	 * @return {Object} l'instance courante
	 */
	setWidth: function(){
		var _width = this.options.length * this.options.itemWidth;
		if(_width > 0) this.container.css({width: _width});
		return this;
	},
	
	/**
	 * Retourne la largeur courante du container des éléments
	 * @return largeur du container HTML en pixels
	 */
	getWidth: function(){
		return this.container.innerWidth();
	},
	
	/**
	 * Deplace le container des éléments
	 * A la fin du mouvement de deplacement lancement un trigger sur l'evenement stopMove
	 * A utiliser pour une fonction optionnelle de callback
	 * @param {Number} dist
	 * @return {Object} l'instance courante
	 */
	moveTo: function(dist, direction){
		this.container.stop().animate({left: dist}, {duration: this.options.duration, easing: this.options.easing, complete: function(){
			$(this).trigger('stopMove');
			(direction == 'prev')? $(this).trigger('stopMovePrev') : $(this).trigger('stopMoveNext');
		}.bind(this)});
		return this;	
	}
});
 
/**
  * Caroussel Widget Elément
  * @params container : HTML elt.
  * @options Hash contenant les options custom de l'élément
  * @methods
  * 	initialize();
  * 	getWidth();
  * @return {Object} l'instance courante
	*/
 rvcq.CarousselElt = function(container, options){
 	this.defaultOptions = {duration: 350, easing: 'easeOutCubic', speed: 'slow'};
	this.options = $.extend({}, this.defaultOptions, options);
	this.container = $(container);
	this.isActive = (this.container.hasClass('.active'))? true : false;
	return this.initialize();
};
 
$.extend(rvcq.CarousselElt.prototype, {
 	initialize: function(){
		return this;
	}, 
	
	/**
	 * Trouve la largeur d'un élément
	 * @return largeur du container de l'élément HTML en pixels
	 */
	getWidth: function(){
		var width = 0;
		var $parent = this.container.parents('li:eq(0)');
		if($parent.is('li')){
			width = $parent.innerWidth();			
		}
		else width = this.container.outerWidth(true);
		return width;
	}
});
 
rvcq.SuperCaroussel = function(container, options){
	rvcq.SuperCaroussel.parentClass.constructor.call(this, container, options);
	this.timeout = null;
	this.delay = 12000;
	return this._initialize();
};

$(new Object()).extendClass(rvcq.SuperCaroussel, rvcq.Caroussel);

$.extend(rvcq.SuperCaroussel.prototype, {
	_initialize: function(){
		
		this.btns.each(function(i, elt){
			var $btn = jQuery(elt);
			$btn.bindAsEventListener('click', function(e){
				rvcq.tools.stopEvent(e);
				if(this.timeout) window.clearTimeout(this.timeout);
				return false;
			}, this, $btn);
		}.bind(this));
		
		$(this.scroller).bind('stopMove', function(e){
			this.setAutoScroll();
		}.bind(this));
		
		if(!this.timeout) {
			this.timeout = window.setTimeout(function(){
				this.jump();
			}.bind(this), this.delay);
		}
		
		return this;
	},
	
	jump: function(){
		if(!arguments[0]){
			if((this.index+this.options.display) >= this.items.length){
				this.jump(1);
			}	else this.moveTo();
		}
		else{
			var step = arguments[0];
			if(step == this.index+1) return;
			var index = (step > this.index+1)? 1 - step : -1*(step - 1);
			var dist = this.items[0].getWidth() * index;
			var duration = this.scroller.options.duration*Math.abs(this.index-(step-1));
			this.isInProcess = true;
			var that = this;
			this.scroller.container.stop().animate({left: dist}, {duration: duration, complete: function(){
				$(this).trigger('stopMove');
				that.isInProcess = false;
				that.index = step - 1;
				that.setBtnsAvailability();
				$(this).trigger('endProcess');
			}.bind(this.scroller)});
		}
	},
	
	setAutoScroll: function(){
		if(this.timeout) window.clearTimeout(this.timeout);
		this.timeout = window.setTimeout(function(){
			this.jump();
		}.bind(this), this.delay);
		return this;
	}
});
 
/**
* Accordeon Widget
*/
rvcq.Accordeon = function(container, options){
	this.defaultOptions = {duration: 350, easing: 'easeOutCubic', speed: 'slow', visible: false};
	this.options = $.extend({}, this.defaultOptions, options);
	this.container = $(container);
	return this.initialize();
};

$.extend(rvcq.Accordeon.prototype, {
	initialize: function(){
		$('ul div.scroller', this.container).hide();
		$('ul .open div.scroller', this.container).slideDown();
		var $a = $('li a', this.container);
		$a.each(function(i, elt){
			var $next = $(elt).next();
			if($next.is('div.scroller')){
				var $elt = $(elt);
				$elt.bindAsEventListener('click', function(e){
					rvcq.tools.stopEvent(e);
					if($next.is(':visible')) return false;
					else {
						var $visible = $('ul div.scroller:visible', this.container);
						var parent = $visible.parents('li:eq(0)');
						$visible.hide();
						$(parent).removeClass('open');
						var parent = $next.parents('li:eq(0)');
						$(parent).addClass('open');
						$next.slideDown('normal');
						return false;
					}
				}, this);
			}
		}.bind(this));
		return this;
	}
});

/**
* Accordeon Ext. Widget
*/
rvcq.SuperAccordeon = function(container, options){
	rvcq.SuperAccordeon.parentClass.constructor.call(this, container, options);
};

$(new Object()).extendClass(rvcq.SuperAccordeon, rvcq.Accordeon);

$.extend(rvcq.SuperAccordeon.prototype, {
	initialize: function(){
		$('ul li.open', this.container).removeClass('open').each(function(i, elt){
			$(elt).addClass('open');
			window.setTimeout(function(){
				$('div', elt).slideDown('normal');
			}, 500);
		});
		
		var $a = $('li a', this.container);
		$a.each(function(i, elt){
			var $next = $(elt).next();
			if($next.is('div')){
				var $elt = $(elt);
				$elt.bindAsEventListener('click', function(e){
					rvcq.tools.stopEvent(e);
					var parent = $elt.parents('li:eq(0)');
					if($next.is(':visible')){
						$next.slideUp('normal', function(){
							$(parent).removeClass('open');
						});
					}
					else {
						$(parent).addClass('open');
						$next.slideDown('normal', function(){
							parent.addClass('open');
						});
						return false;
					}
					return false;
				}, this);
			}
		}.bind(this));
		return this;
	}
});
 
/**
* Panel Widget
*/
rvcq.Panel = function(container, options){
	this.defaultOptions = {duration: 350, easing: 'easeOutCubic', speed: 'slow', visible: false};
	this.options = $.extend({}, this.defaultOptions, options);
	this.container = $(container);
	this.btn = $('#panel_btn', this.container);
	return this.initialize();
};
	
$.extend(rvcq.Panel.prototype, {
	initialize: function(){
		this.btn.bind('click', function(e){
			rvcq.tools.stopEvent(e);
			(!this.options.visible)? this.show() : this.hide();
			return false;
		}.bind(this));
			
		if(this.options.visible) this.show();
		return this;
	},
		
	show: function(){
		this.options.visible = true;
		this.container.addClass('open');
		this.container.stop(true, true).animate({left: 0}, this.options.speed, this.options.easing, function(){
			//callback
		}.bind(this));
		return this;
	},
		
	hide: function(){
		this.options.visible = false;
		var width = -1*(this.container.outerWidth(true) - 8);
		this.container.stop(true, true).animate({left: width}, this.options.speed, this.options.easing, function(){
			this.container.removeClass('open');
		}.bind(this));
		return this;
	}
});

rvcq.search = function(params)
{
  this.params = params.get_params;
  this.url = params.url;
  this.ajax_target = params.ajax_target;
  this.on_reload = params.on_reload;
};

rvcq.search.prototype.setParam = function(key, value)
{
  this.params[key] = value;
};

rvcq.search.prototype.reload = function()
{
  this.params.ajax = 1;
  var that = this;
  jQuery.ajax({
     dataType : 'html', 
     url : this.url, 
     data : this.params, 
     type: 'POST', 
     error : function(request, textStatus, errorThrown)
     {
       alert(heap.translate('err_ko'));
     }, 
     success : function(response)
     {
       jQuery(that.ajax_target).html(response);
       if (that.on_reload) that.on_reload();
     }
   });
};

rvcq.agenda = function(params)
{
  this.ajax_url = params.url;
  this.space = $(params.selector);
  this.page = 1;
  var that = this;
  $(document).ready(function() {
    $('a.btn_agenda').hitch('click', that.on_add, that);
  });
  this.init();
};

rvcq.agenda.prototype.init = function(mode)
{
  if (!mode || mode == 'auto') mode = this.space.find('#agenda_mode').text();
  //Init this mode
  var that = this;
  this.space.find('.error').hide();
  this.space.find('input.text').each(function () {
    var input = this;
    var orig_text = $(input).val();
    var error_span = that.space.find('.error.'+$(input).attr('name'));
    $(input).bind('focus', function() {
      if ($(input).val() == orig_text) $(input).val('');
      error_span.hide();
    }).bind('blur', function() {
      if ($(input).val() == '') $(input).val(orig_text);
    });
  });
  
  switch (mode)
  {
    case 'login' : 
      this.space.find('form#login').hitch('submit', function(e){
				rvcq.tools.stopEvent(e);
				this.login();
				return false;
			}, this);
      this.space.find('#password_reset').bind('click', function () { that.refresh('pw_recovery'); return false; });
      this.space.find('#subscribe').bind('click', function () { that.refresh('subscribe'); return false; });
      break;
    case 'pw_recovery' : 
      this.space.find('form#recovery').hitch('submit', this.pw_recovery, this);
      this.space.find('#login').bind('click', function() { that.refresh('login'); return false; });
      break;
    case 'pw_recovery_conf' :
      this.space.find('#login').bind('click', function() { that.refresh('login'); return false; });
      break;
    case 'pw_modify' : 
			this.space.find('#favoris').bind('click', function() { that.refresh('favoris'); return false; });
      this.space.find('form#update').hitch('submit', this.pw_modify, this);
      break;
    case 'pw_modify_conf' :
      this.space.find('#favoris').bind('click', function() { that.refresh('favoris'); return false; });
      break;
    case 'subscribe' : 
      this.space.find('form#subscribe').hitch('submit', this.subscribe, this);
			this.space.find('#login').bind('click', function() { that.refresh('login'); return false; });
      break;
    case 'register_email_sent' :
      this.space.find('#login').bind('click', function() { that.refresh('login'); return false; });
      break;
    case 'favoris' : 
      this.space.find('a.agenda_remove').hitch('click', this.on_remove, this);
      this.space.find('#agenda_logout').hitch('click', this.logout, this);
      this.space.find('#pw_modify').bind('click', function () { that.refresh('pw_modify'); return false; });
      break;
  }
};

rvcq.agenda.prototype.subscribe = function()
{
  var that = this;
  var email = this.space.find('input#email').val();
  var email_confirm = this.space.find('input#email-confirm').val();
  if (email != email_confirm) { this.space.find('.error.email-confirm').show(); return false; }
  var username = email.replace(/[^a-zA-Z0-9]/, "");
  var params = {
    'email' : email, 
    'password' : this.space.find('input#password').val(), 
    'password-confirm' : this.space.find('input#password-confirm').val(), 
    'newsletter' : (this.space.find('input#newsletter:checked').val() != null ? 1 : 0)
  };
  heap.api.rvcq.users.create(function(response) {
    if (response.type != heap.SUCCESS)
    {
      if (response.code == 'ERR_VALIDATION_FAILED') {
        for (var key in response.data) {
          var text = rvcq.translate(response.data[key]);
          that.space.find('.error.'+key).text(text).show();
        }
      } else {
        rvcq.error(response.msg);
      }
      return;
    }
    that.refresh('register_email_sent', { email : email });
  }, params);
  return false;
};

rvcq.agenda.prototype.pw_modify = function()
{
  var that = this;
  var params = {
    'slug' : this.space.find('input#slug').val(), 
    'username' : this.space.find('input#slug').val(), 
    'email' : this.space.find('input#email').val(), 
    'password' : this.space.find('input#password').val(), 
    'password-confirm' : this.space.find('input#password-confirm').val(), 
    'newsletter' : (this.space.find('input#newsletter:checked').val() != null ? 1 : 0)
  };
  heap.api.rvcq.users.edit(function(response) {
    if (response.type != heap.SUCCESS) {
      if (response.code == 'ERR_VALIDATION_FAILED') {
        for (var key in response.data) {
          that.space.find('.error.'+key).show();
        }
      } else {
        rvcq.error(response.msg);
      }
      return;
    }
    that.refresh('pw_modify_conf');
  }, params);
  return false;
};

rvcq.agenda.prototype.pw_recovery = function()
{
  var that = this;
  var params = {
    email : this.space.find('input#r_email').val()
  };
  heap.api.rvcq.users.recovery(function(response) {
    if (response.type != heap.SUCCESS) {
      that.space.find('.error.r_email').show();
      return;
    }
    that.refresh('pw_recovery_conf', { email: params.email });
  }, params);
  return false;
};

rvcq.agenda.prototype.login = function()
{
  var params = {
    email : this.space.find('input#email').val(), 
    password : this.space.find('input#password').val()
  };
  var that = this;
  that.space.find('.error').hide();
  heap.api.users.login(function(response) { 
    if (response.type != heap.SUCCESS) {
      if (response.code == 'AUTH_WRONG_LOGIN') {
        that.space.find('.error.email').show();
      } else if (response.code == 'AUTH_WRONG_PASSWORD') {
        that.space.find('.error.password').show();
      } else {
        rvcq.error(response.msg);
      }
      return false;
    }
    that.refresh();
  }, params);
  return false;
};

rvcq.agenda.prototype.logout = function()
{
  var params = {};
  var that = this;
  heap.api.users.logout(function(response) {
    if (response.type != heap.SUCCESS) {
      rvcq.error(response.msg);
    }
    that.refresh();
  }, params);
  return false;
};

/**
 * Valid modes:
 * login
 * password_reset
 * password_modify
 * subscribe
 * favoris
 * pw_email_sent
 * pw_modify
 * pw_modify_conf
 * register_confirm
 * register_email_sent
**/
rvcq.agenda.prototype.refresh = function(mode, params)
{
  if (!mode) mode = 'auto';
  var data = { mode: mode, agenda_page : this.page };
  if (params) {
    for (var key in params) data[key] = params[key];
  }
  
  var that = this;
  var refreshCB = function(response)
  {
    that.space.find('#ajax_area').html(response);
    that.init(mode);
  };
  $.ajax({
    dataType: 'html', 
    error: function(a,b,c) { rvcq.error('Une erreur est survenue.'); }, 
    success: refreshCB, 
    url: this.ajax_url, 
    data: data
  });
};

rvcq.agenda.prototype.add = function(show_id, callback)
{
  var params = { 'show_id' : show_id };
  var that = this;
  heap.api.rvcq.shows.addToAgenda(function(response) {
    if (response.type != heap.SUCCESS) {
      rvcq.error(response.msg);
      return;
    }
    that.refresh();
    if (callback) callback();
  }, params);
  return false;
};

rvcq.agenda.prototype.remove = function(show_id, callback)
{
  var params = { 'show_id' : show_id };
  var that = this;
  heap.api.rvcq.shows.removeFromAgenda(function(response) {
    if (response.type != heap.SUCCESS) {
      rvcq.error(response.msg);
      return;
    }
    that.refresh();
    if (callback) callback();
  }, params);
  return false;
};

rvcq.agenda.prototype.get_page = function(page_num)
{
  this.page = page_num;
  this.refresh();
  return false;
};

rvcq.agenda.prototype.on_add = function(event, btn)
{
  var elem = $(event.target);
  var show_id = elem.attr('rel');
  this.add(show_id, function() {
 		var target = $('a.btn_agenda[rel='+show_id+']');
		if(btn) target = $(btn);
		target.hide();
  });
  
  return false;
};

rvcq.agenda.prototype.on_remove = function(event)
{
  var elem = $(event.target);
  var show_id = elem.attr('rel');
  this.remove(show_id, function() { 
    $('a.btn_agenda[rel='+show_id+']').show();
  });
  return false;
};

