/* ******************************************************************************* */
/* 			Some various stuff coded by myself			   */
/*			   ( later come foreign code )				   */
/* ******************************************************************************* */


var debug=function(dbg_level,to_alert){if(dbg_level)alert(to_alert);}

var mouse = { x:0, y:0 }; //< Keep mouse coords
var editors = [];	  //< Needed for BBCode editors
var cache = {};		  //< An empty object wich can be utilized when non-anonymous func/obj is required

var ie = false;		  // IE ? if not, false, if it is, the navigator version

Event.onReady(function(){
/*
	// PNGFIX for IE 5.5, 6
	if (document.all && /MSIE (5\.5|6)/.test(navigator.userAgent) &&
		document.styleSheets && document.styleSheets[0] && document.styleSheets[0].addRule) {
			document.styleSheets[0].addRule('img', 'behavior: url(/webroot/styles/iepngfix.htc)');
		}
*/
	// Quick & dirty IE detection
	if (document.all && /MSIE/.test(navigator.userAgent)){
		if(/MSIE (5\.5|6)/.test(navigator.userAgent)) ie = '6';
		else if(/MSIE (7)/.test(navigator.userAgent)) ie = '7';
		else if(/MSIE (8)/.test(navigator.userAgent)) ie = '7';
		else ie = true;
	}

	// BBCode light Editors
	$$('.bbeditor').each(function(e){
        	editors[e.id] = new bbeditor(e);
	});

	// Textarea selection handling.
	Element.addMethods('textarea', textareaSelection);

	// Element.insertAfter()
	Element.addMethods({
		insertAfter: function (e,element,afterMe) {
			return $(e).insertBefore($(element),$(afterMe).nextSibling);
		}
	});

	// Get mouse coords always avaibles
	Event.observe(document,'mousemove', function(event){
		mouse.x = Event.pointerX(event);
		mouse.y = Event.pointerY(event);
	});

	//todo move that in a kind of "buisness logic", less specialized 
	// javascript functions file.
/*	new Effect.Fade($('blank'),{duration: 0.5}); */


	$$(".AvatarJSRightPanel").each(function(e){ e.hide(); });


});

/**
 * BBCode Lightweight Editor
 * Transform a classic textarea into a light bbcode editor.
 *
 * // TODO: Many things, in wich: 
 * 	- Guess site url or ask site url ( for images url )
 * 	- Get A Better & more complete toolbar.
 * 	- !important Resize preview div when resizing the viewport.
 *
 * Usage: Just need to set textarea inside a div with both having an id 
 * 	  and textarea having the className: "bbeditor"
 * 	  For instance:
 * 	   	     <div id="foo">
 * 			<textarea id="footxt" class="bbeditor"></textarea>
 * 		     </div>
 */
var bbeditor = Class.create({
	mode: 'edition',
	options: {
		toPreviewButtonText: 'Previsualisation',
		fromPreviewButtonText: '< Retour Edition',
		boardPadding: 20,
		boardBorderWidth: 2
	},

	initialize: function() {
		this.toolbox  = Builder.node('ul',{className:'toolbox'});
		this.board    = Builder.node('div',{className:'board'});
		this.textarea = $(arguments[0]);
		this.editor   = this.textarea.up('div');

		this.editor.className = 'editor';
		this.initToolbox();
		this.editor.insert(this.toolbox,{position:'before'});
		this.editor.insert(this.textarea,{position:'after'});

		this.editor.insert(this.board,{position:'after'});

		this.board.setStyle({
			height: (this.textarea.getHeight() 
				- (this.options.boardPadding * 2) 
				- (this.options.boardBorderWidth * 2) ) + 'px',
			width:  (this.textarea.getWidth() 
				- (this.options.boardPadding * 2) 
				- (this.options.boardBorderWidth * 2) ) + 'px'
		}).hide();
		this.toolbox.setStyle({
			width:  this.textarea.getWidth() 
				- ( this.options.boardPadding * 2)
				- ( this.options.boardBorderWidth * 2) + 'px'
		});
	},

	insertBB: function ( bb ) {
		
		// IE
		if(document.selection)
		{
			this.textarea.focus();
			var sel = document.selection.createRange();
			sel.text = '['+ bb +']'+ sel.text +'[/'+ bb +']';
		}
		// Moz
		else 
		{
			var len   = this.textarea.value.length;
			var start = this.textarea.selectionStart;
			var end   = this.textarea.selectionEnd;

			var sel = this.textarea.value.substring(start, end);
			var rep = '['+ bb +']' + sel + '[/'+ bb +']';
			this.textarea.value = this.textarea.value.substring(0,start) 
				+ rep 
				+ this.textarea.value.substring(end,len);
		}
	},
	  
	insertSmiley: function ( sm ) {
		//IE
		if(document.selection)
		{
			this.textarea.focus();
			var sel = document.selection.createRange();
			sel.text = sel.text + ':'+ sm +':';
		}
		//Moz
		else
		{
			var len   = this.textarea.value.length;
			var end   = this.textarea.selectionEnd;

			this.textarea.value = this.textarea.value.substring(0,end) 
				+ this.regexps[sm] + this.textarea.value.substring(end,len);
		}
	},

	initToolbox: function () {
		['u','i','b'].each(function(s){
			this.toolbox.appendChild(Builder.node('li',
				Builder.node('a',{href:
					'javascript:editors[\''
					+ this.textarea.id 
					+'\'].insertBB(\''+s+'\');'},s)
			));
		},this);

		// Smileys
		[	'smile','wink','cry',
			'shocked', 'tux','heart','kiss'
		].each(function(s){
			this.toolbox.appendChild( Builder.node('li',
				Builder.node('a',{
					href: 'javascript:editors[\''
					+ this.textarea.id
					+ '\'].insertSmiley(\''+ s +'\');'
					,className: 'smileyButton'
				},Builder.node('img',{src:this.sm(s,{onlySrc:true})})
			)));
		},this);

		this.toolbox.appendChild(
			Builder.node('li', this.button = Builder.node('button',{
				className: 'open',
				type: 'button',
				onclick: 'editors[\'' + this.textarea.id + '\'].preview();'
				}, this.options.toPreviewButtonText )
			));
	},

	preview: function(e) {
		if(this.mode == 'preview') {
			this.mode = 'edition';
			return this.fromPreview(e);
		} else {
			this.mode = 'preview';
			return this.toPreview(e);
		}
	},

	fromPreview: function (e) {
		this.button.update( this.options.toPreviewButtonText );
		this.board.hide();
	},
	regexps: {
		'smile': ':-)',
		'wink' : ';-)',
		'cry': ':\'-(',
		'shocked': ':-|',
		'tux': ':tux:',
		'heart': ':heart:',
		'kiss': ':kiss:'
	},

	toPreview: function (e) {
		this.board.setStyle({
			position: 'absolute',						    // +1 ? pkoi ?
			top: ((this.toolbox.cumulativeOffset().top) + this.toolbox.getHeight() + 1 ) + 'px',
			left: this.toolbox.cumulativeOffset().left  + 'px'
		}).show();

		var tmp = this.textarea.value.stripTags();
		regexps = [

			// BBCode
			{ pattern: /(\[b\]([\S\s]*?)\[\/b\])/gim, replace: '<b>$2</b>' },
			{ pattern: /(\[u\]([\S\s]*?)\[\/u\])/gim, replace: '<u>$2</u>' },
			{ pattern: /(\[i\]([\S\s]*?)\[\/i\])/gim, replace: '<i>$2</i>' },
			{ pattern: /(\[url\]([\S\s]*?)\[\/url\])/gim, replace: '<a href="$2">$2</a>' },
			{ pattern: /(\[QUOTE="?(.*)"?\]([\S\s]*?)\[\/QUOTE\])/gim,
			  replace: '<div class="quote"><span class="title"><span class="quoted">$2</span>'
					  +' à écrit:</span><quote>$3</quote></div>' 
			},
			{ pattern: /(\[COLOR=#([0-9A-Fa-f]{3,6})\]([\S\s]*?)\[\/COLOR\])/gim,
			  replace: '<span style="color:#$2;">$3</span>' 
			},

			// Smiley
			{ pattern: /:-?\)/gim, 	replace: this.sm('smile') },
			{ pattern: /;-?\)/gim, 	replace: this.sm('wink') },
			{ pattern: /:'-?\(/gim, replace: this.sm('cry') },
			{ pattern: /\:-\|/gim, 	replace: this.sm('shocked') },
			{ pattern: /:tux:/gim, 	replace: this.sm('tux') },
			{ pattern: /:heart:/gim,replace: this.sm('heart') },
			{ pattern: /:kiss:/gim, replace: this.sm('kiss') }

		].each(function(rgxp){
			tmp = tmp.replace(rgxp.pattern, rgxp.replace);
		}, this );

		this.board.update(tmp.gsub("\n",'<br/>'));
		this.button.update(this.options.fromPreviewButtonText);
	},

	sm : function () {
		smileyName = arguments[0];
		onlySrc    = arguments[1] || false;
		smileyDir  = "/webroot/images/smileys/";

		if(onlySrc) {
			return smileyDir + smileyName + '.gif';
		} else {
			return 	'<img src="'+ smileyDir
				+ smileyName + '.gif" alt="' 
				+ smileyName + '" class="asmiley" />';
		}
	}
});


/**
 * Handle Selection & Carret position in Textarea
 * ( Used for instance in BBCode editor )
 * Usage:
 * 	Extends the DOM textarea class.
 */
var textareaSelection = {
	test: function (element, text) {
		element.replaceSelection(text, true);
	},
	
	getSelection: function (element) {
		if (element.setSelectionRange)
			return element.value.substring(element.selectionStart, element.selectionEnd);
		else if (document.selection) {
			element.focus();
			return document.selection.createRange().text;
		}
	},
	
	getSelectionStart: function(element) {
		if ( typeof element.selectionStart != 'undefined' )
			return element.selectionStart;
		
		// IE Support
		element.focus();
		var range = element.createTextRange();
		range.moveToBookmark(document.selection.createRange().getBookmark());
		range.moveEnd('character', element.value.length);
		return element.value.length - range.text.length;
	},

	getSelectionEnd: function(element){
		if ( typeof element.selectionEnd != 'undefined' )
			return element.selectionEnd;

		// IE Support
		element.focus();
		var range = element.createTextRange();
		range.moveToBookmark(document.selection.createRange().getBookmark());
		range.moveStart('character', - element.value.length);
		return range.text.length;
	},
	
	setCaretPos: function(element, start, end) {
		end = end || start;
		element.focus();
		if (element.setSelectionRange)
			element.setSelectionRange(start, end);
		else if (document.selection) {
			var range = element.createTextRange();
			range.moveStart('character', start);
			range.moveEnd('character', - element.value.length + end);
			range.select();
		}
	},

	replaceSelection: function (element, str, keep) {
		element.focus();
		
		var start = element.getSelectionStart();
		var stop = element.getSelectionEnd();
		var end = start + str.length;
		var scrollPos = element.scrollTop;
			
		element.value = element.value.substring(0, start) + str + element.value.substring(stop);
		if ( keep ) element.setCaretPos(start, end);
		else element.setCaretPos(end);
		element.scrollTop = scrollPos;
	}

};


/**
 * panelAble
 * Allow to convert ( and undo ) a div
 * to a fixed panel at right of screen.
 * Usage: 
 * 	p = new panelAble('idOfDiv');
 * 	p.toggle(this)
 */
var panelAble = Class.create({
	initialize: function (e) {
		this.e = $(e);
	},

	panel: function (caller) {
		caller.update('< remetre');
		this.e.style.position =  'absolute';
		this.updateOnResize();
		this.updateOnScroll();

		cache.updateOnScroll = this.updateOnScroll.bindAsEventListener(this);
		cache.updateOnResize = this.updateOnResize.bindAsEventListener(this);
		Event.observe(document, 'scroll', cache.updateOnScroll);
		Event.observe(window, 'resize', cache.updateOnResize);
	},

	updateOnScroll: function () {
		var scroll = document.viewport.getScrollOffsets();
		this.e.style.top = scroll.top + 'px';
	},

	updateOnResize: function () {
		var h = document.viewport.getHeight();
		var l = ( document.viewport.getWidth() - this.e.getWidth() - 30);
		this.e.setStyle({
			height: (h -40 ) + 'px',
			left: l + 'px'
		});
	},

	depanel: function (caller) {
		caller.update('attacher >');
		Event.stopObserving(document, 'scroll', cache.updateOnScroll);
		Event.stopObserving(window, 'resize', cache.updateOnResize);
		this.e.setStyle({
			top: '',
			left: '',
			height: ''
		});
		this.e.relativize();
	},

	toggle: function (caller) {
		if(this.e.style.position != 'absolute') {
			this.panel(caller);
		} else {
			this.depanel(caller); 
		}
	}
});

/**
 * Panel a droite de l'avatar, aparaissant au survol de la souris.
 */
var avRPan = {
	e_height: 0,
	e_width: 0,
	show: function (caller) {
			var e = $(caller.nextSibling);
			if(e.style.display == "none") {
				e.show();
				e.style.position = "absolute";
				
				// IE hack
				if(ie != false) ie_fix = $(caller).firstChild.getHeight();
				else ie_fix = 0;
				
				e.setStyle({
					top: ( $(caller).cumulativeOffset().top 
					       - e.getHeight() + 10  + ie_fix )
					       + 'px',
					left: ( $(caller).cumulativeOffset().left 
						+ $(caller).getWidth() ) 
						+ 'px'
				});
				e_height = e.getHeight();
				e_width = e.getWidth();
			}

	      },
	hide: function (caller) {
			var e =$(caller.nextSibling);
			
			var xmin = e.cumulativeOffset().left -10;
			var xmax = e.cumulativeOffset().left + e_width - 5;
			var ymin = e.cumulativeOffset().top + 7; 
			var ymax = e.cumulativeOffset().top + e_height - 7;

			if(!(mouse.x>=xmin && mouse.x<=xmax && mouse.y>=ymin && mouse.y<=ymax)) {
				e.hide();
			}
	      }
}
/**
 * the main drop down menu
 */
var dropDownMenu = {
	
	init : function () {
		//$$('.ddm').each(function(el){
		//
		//	FIXME:	ne marche pas sous IE7,
		//		m'a donc obligé à mettre le code "inline" dans le menu.
		//
		//	el.setAttribute('onmouseover', 'dropDownMenu.showMenu(this);' );
		//	el.setAttribute('onmouseout', 'dropDownMenu.hideMenu(this);' );
		//});
	},
	
	showMenu : function (el) {
		el = $(el);
		el_child = $('dd_'+el.id);
		
		el_child.style.left = ( el.viewportOffset().left ) + 'px';
		if(ie){	// IE Hack
			el_child.style.top = ( 
					el.viewportOffset().top +
					el.getHeight()
				) + 'px';
		}
		el_child.show();
	},
	
	hideMenu : function (el) {
		$('dd_'+el.id).hide();
	}
}

/**
 * Win
 * Create JS windows~popup
 * Usage:
 * 	var popup = new win({width:400, content: 'theDivId'});
 * 	win.open();
 * 	win.close();
 * 	win.update('new_content');
 * 	   .... and having html:
 * 	<div id="theDivId">
 * 		<div style="border: 1px solid #000;">
 * 			I AM THE <b>MAIN</b> CONTENT :)
 * 		</div>
 * 	</div>
 * XXX 
 * XXX WARNING: doit ABSOLUEMENT être appellé Après l'arbre DOM 
 * XXX 		ENTIEREMENT chargé !! ( surtout sous IE ! )
 * XXX
 */
var win = Class.create({
	initialize : function () {
		this.width   = arguments[0].width   || 300 ;
		this.height  = arguments[0].height  || 'auto' ;
		this.content = arguments[0].content || null;
		this.closeBtnLabel = arguments[0].closeBtnLabel || 'Fermer';
		
		var W = Builder.node('div',{className:'ymswinpop'});

		//FIXME Builder.node w/ IE bug hack	
		//if(!W.update)Element.extend(W);

		W.hide();
		var cont = Builder.node('div');
		var close = Builder.node('a',{
			className:'open',
			style: 'float: right;',
			href: 'javascript://close'
		});
		
		//FIXME Builder.node w/ IE bug hack	
		//if(!close.update)Element.extend(close);
		//if(!cont.update)Element.extend(cont);
		
		close.update(this.closeBtnLabel);

		document.body.appendChild(W);
		var upd = ''; if(this.content !== null ){ upd = $(this.content).innerHTML; }
		cont.update(upd);
		W.insert(close,{position: 'after'});
		W.insert(cont,{position: 'after'});
		W.setStyle({
			padding: '0px',
			position: 'absolute',
			height: 'auto',
			width: this.width + 'px'
		});

		W.show();
		if(this.height === 'auto') {
			this.height = close.getHeight() + cont.getHeight();
		}
		W.hide();

		var dims = document.viewport.getDimensions();
		var h = ((dims.height/2).floor()) - ((this.height/2).floor());
		var w = ((dims.width/2).floor()) - ((this.width/2).floor());
		W.setStyle({ 'top': h + 'px', left: w + 'px' });

		Event.observe(close,'click',function(event){
			var e = Event.element(event);
			Effect.Fade(e.up('.ymswinpop'));
		});

		this.W = W;
		this.cont = cont;
		this.close_btn = close;
	},

	close_btn : null,
		update_btn_close: function ( newname ) {
		this.close_btn.update(newname);
	},

	refresh_position: function () {
		var scroll = document.viewport.getScrollOffsets();
		var dims = document.viewport.getDimensions();
		var h = ((dims.height/2).floor()) - ((this.height/2).floor()) + scroll.top;
		var w = ((dims.width/2).floor()) - ((this.width/2).floor()) + scroll.left;
		this.W.setStyle({ 'top': h + 'px', left: w + 'px' });
	},

	open: function () {
		this.refresh_position();
		Effect.Appear(this.W); 
	},

	close: function () {
		Effect.Fade(this.W);
	},

	update: function (content) {
		if(content != undefined){
			(this.cont.down() || this.cont).update(content);
		} else {
			var upd = ''; if(this.content !== null ){ upd = $(this.content).innerHTML; }
			(this.cont.down() || this.cont).update(upd);
		}
	}
});


/* ******************************************************************************* */
/*				Other's codes					   */
/* ******************************************************************************* */


/**
 * Array Sum, Max & Min
 * Usage:
 * 	[1,3,6].max(); // (i.e. )
 */
Array.prototype.sum = function(){
	for(var i=0,sum=0;i<this.length;sum+=this[i++]);
	return sum;
}
Array.prototype.max = function(){
	return Math.max.apply({},this)
}
Array.prototype.min = function(){
	return Math.min.apply({},this)
}

/**
 * Helper Effect for resizing elements...
 * Copyright(c) 2007 - Frost Innovation AS, http://ajaxwidgets.com
 */
Effect.ReSize = Class.create();
Object.extend(Object.extend(Effect.ReSize.prototype, Effect.Base.prototype), {
  initialize: function(element) {
    this.element = element;
    if(!this.element) throw(Effect._elementDoesNotExistError);
    var options = Object.extend({ amount: 100, direction: 'vert', toSize:null }, arguments[1] || {});
    if( options.direction == 'vert' )
      this.originalSize = options.originalSize || parseInt(this.element.style.height);
    else
      this.originalSize = options.originalSize || parseInt(this.element.style.width);

    if( options.toSize != null )
      options.amount = options.toSize - this.originalSize;

    this.start(options);
  },
  setup: function() {
    // Prevent executing on elements not in the layout flow
    if(this.element.getStyle('display')=='none') { this.cancel(); return; }
  },
  update: function(position) {
    if( this.options.direction == 'vert' ){
      this.element.setStyle({height: this.originalSize+(this.options.amount*position)+'px'});
    } else {
      this.element.setStyle({width: this.originalSize+(this.options.amount*position)+'px'});
    }
  },
  finish: function(){
    if( this.options.direction  == 'vert' ){
      this.element.setStyle({height: this.originalSize+this.options.amount+'px'});
    } else {
      this.element.setStyle({width: this.originalSize+this.options.amount+'px'});
    }
  }
});
