/*
 * RichHTML v1.0.0 - jQuery/mustache.js grid control
 * Copyright (c) 2012 Alberto Vasquez
 *
 * www: http://www.richhtml.com
 * email: support@richhtml.com
 */

RichHTML.msgBox = function (content, config, callback)
{
    var msgBox = new RichHTML.window({});
    
    msgBox.options.escClose = false;
    msgBox.options.type = "alert"; //alert,info,error,prompt,confirm
    msgBox.options = $.extend(msgBox.options,config);
    msgBox.options.content = content;
    if (callback) {
    	msgBox.options.afterClick = callback;
    } else {
    	msgBox.options.afterClick = null;
    }
    if (msgBox.options.title === '') {
    	msgBox.options.hideTitle = true;
    }
    msgBox.show();

    //might not center if you pass url
	RichHTML.center($('#'+msgBox.id+' .window-description-elements'),$('#'+msgBox.id+' .window-description form'));   
	
	if (typeof msgBox.options.afterClick === 'function' && 
			   msgBox.options.afterClick != false) {
		$(msgBox).bind({    
		    "buttonclick" : function(event,data) {
		    	var elements, args = [];
		    	elements = msgBox.form.serializeArray();    	
	    		data.elements = {};		    	
		    	for(var i=0;i<elements.length;i++) {
		    		data.elements[elements[i].name] = elements[i].value;
		    	}
				args.push(data);			    			
		    	msgBox.options.afterClick.apply(self,args);
		    }
	    });
    }
	 
}


RichHTML.window = function(config){
	var defaults, self=this;
	
	self.id = null;
	self.hasButtons = false;
	self.name = 'richwindow';
	self.delayLoad = false;
	self.form = null;
	self.params = {};
	
	defaults = {
		content: null,
        width: 360,
        type: "form",
        showSubmit: false,
        showDelete: false,        
        hideButtons: false,
        escClose: true,
        hideTitle: false,
        useOverlay: true,
        transition: 0,
        title: ''
    };
    
    self.options =  $.extend(defaults, config);

	self.elements = {
		firstElement: null,
		lastElement:null,
		firstGroup:null,
		lastGroup:null
	};

    if (config.id) {self.id = config.id;}
    else {self.id = self.getId();}    
    
   	self.template = '<div class="richwindow" id="{richid}" style="width:{width};"><div class="window-bg" style="width:{width};">';
   	self.template += '<div class="window-title" style="width:{width};">{title}</div>';
   	self.template += '<div class="window-description {msgboxclasses}" style="height:{height};"><form action="index.php" id="form-description-{richid}" novalidate="novalidate" style="margin-bottom:5px;"><div class="window-description-elements"></div></form></div>';
   	self.template += '<div class="window-buttons">{{buttons}}</div></div></div>';
   	   	
	//lets bind esc to the form hide
	self.closeKeyHandler = function(e) {
		if (e.keyCode === 27 && self.options.escClose) {
            self.hide()
        }
	};
	
	//prevents the form from submitting
	self.enterKeyHandler = function (e) {
        if (e.keyCode === 13) {
           if ($(document.activeElement).hasClass('rich-button')) {
               $(document.activeElement).click();
           }
           
		   if(!$(document.activeElement).is('textarea')) {
		       e.preventDefault();
	           return false;		       
		   }	                                
        }
    };
    
	//lets bind the first tab to the first form element in our content
	self.tabKeyHandler = function(e) {
        if (e.keyCode === 9) {			
			if ($(e.target).is(self.elements.lastGroup) && !e.shiftKey) {
                self.elements.firstGroup.first().focus();
                e.preventDefault();
            } else if ($(e.target).is(self.elements.firstGroup) && e.shiftKey) {
                self.elements.lastGroup.first().focus();
                e.preventDefault();
            }		    
        }        
    };
    
};

//lets submit the form in window-description
//check to see if jquery validator is supported
//if so validate and if not just submit
RichHTML.window.prototype.callDelete = function (method) {
	var self = this;
	
	if (typeof(self.options.deleteUrl) === "undefined") {
	    RichHTML.debug(1,"You need to define a deleteUrl if you want to use the delete method.");	
	    return false;	
	}
	
	if (self.form === null) {
	    RichHTML.debug(1,"this.form is not set yet via the render method.");	
	    return false;		
	}
	
	if (typeof(method) === "undefined") {
		successMethod = function(data) { 
			if (typeof(self.options.grid)!=="undefined") { self.options.grid.reload(); }
			self.hide(); 
		}
	} else {
		successMethod = function(data) { 
				method(data);
				if (typeof(self.options.grid)!=="undefined") { self.options.grid.reload(); }
				self.hide();				
		 }
	}
	
    $.post(self.options.deleteUrl, self.form.serialize(), successMethod, "json");	
	
};


//lets submit the form in window-description
//check to see if jquery validator is supported
//if so validate and if not just submit
RichHTML.window.prototype.submit = function (method) {
	var self = this;
	if (typeof(self.options.actionUrl) === "undefined") {
	    RichHTML.debug(1,"You need to define an actionUrl if you want to use the submit method.");	
	    return false;	
	}
	
	if (self.form === null) {
	    RichHTML.debug(1,"this.form is not set yet via the render method.");	
	    return false;		
	}
	if (typeof(method) === "undefined") {
		successMethod = function(data) { 
			if (typeof(self.options.grid)!=="undefined") { self.options.grid.reload(); }
			self.hide(); 
		}
	} else {
		successMethod = function(data) { 
				method(data,self.form.serializeArray());
				if (typeof(self.options.grid)!=="undefined") { self.options.grid.reload(); }
				self.hide();				
		 }
	}
	
    $.post(self.options.actionUrl, self.form.serialize(), successMethod, "json");	
	
};

RichHTML.window.prototype.getId = function () {
    return this.id || (this.id = RichHTML.id.apply(this));
};

/* Checking content for duplicates */
RichHTML.window.prototype.checkContent = function () {
	var self = this, itemsDefined = 0;	
	
	(self.options.content !== null) ? itemsDefined++ : itemsDefined;
	(typeof (self.options.el) !== "undefined") ? itemsDefined++ : itemsDefined;
	(typeof (self.options.url) !== "undefined") ? itemsDefined++ : itemsDefined;

	//lets make sure that we are not loading from both div el and url as we only need one
	if ( itemsDefined > 1 ) {
	    RichHTML.debug(1,"You need only one param of el, url, or content to determine where the content is coming from.");	
		return false;
	} else if ( itemsDefined === 0 ) {
	    RichHTML.debug(1,"You need either config param el, url, or content to determine where the content is coming from.");
		return false;
	}
	
	return true;
};

RichHTML.window.prototype.prepTemplate = function () {
	var self = this, content = "";
	
	if (!self.checkContent()) { return false; }

    self.template = RichHTML.replaceAll(self.template,"{richid}",self.id);
    
    if ((self.options.title === '') && (!self.options.hideTitle) ) { self.options.title = 'Empty title'; }
	
	if (self.options.type === "form") {
		self.template = RichHTML.replaceAll(self.template,"{msgboxclasses}","");
	} else {
		self.template = RichHTML.replaceAll(self.template,"{msgboxclasses}","msgbox-wrapper msgbox-"+self.options.type);
	}
    self.template = RichHTML.replaceAll(self.template,"{title}",self.options.title);     
    self.template = RichHTML.replaceAll(self.template,"{width}",self.options.width+"px");
    if (typeof(self.options.height) === "undefined") {  
    	self.template = RichHTML.replaceAll(self.template,"{height}", "auto");    
    } else {
    	self.template = RichHTML.replaceAll(self.template,"{height}", self.options.height+"px");
    }
    self.template = RichHTML.replaceAll(self.template,"{descriptionwidth}",(self.options.width-40)+"px");      
    
	return true;
};

RichHTML.window.prototype.prepButtons = function() {
    var self = this,buttons = '',button;
    for (button in self.options.buttons) {
            buttons +=  '<a href="#" class="rich-button white" id="rich-button-' + button + '"><span class="buttontext">' + self.options.buttons[button].text + '</span></a>';            
    }    
    
    if ((buttons === '') && (self.options.hideButtons)) {
	    self.hasButtons = false;
	    RichHTML.debug(3,"No buttons and hide Ok passed as true");	
    } else if (buttons === '') {
	    self.hasButtons = true;    
	    if (self.options.showSubmit) {
	    	buttons += '<a href="#" class="rich-button white" id="rich-button-submit"><span class="buttontext">Submit</span></a>';
		    if (self.options.showDelete) {
		    	buttons += '<a href="#" class="rich-button white" id="rich-button-delete"><span class="buttontext">Delete</span></a>';
		    }
	    	buttons += '<a href="#" class="rich-button white" id="rich-button-autoclose"><span class="buttontext">Close</span></a>';
	    } else {
		    if (self.options.showDelete) {
		    	buttons = '<a href="#" class="rich-button white" id="rich-button-delete"><span class="buttontext">Delete</span></a>';
		    }	    
	    	buttons += '<a href="#" class="rich-button white" id="rich-button-autoclose"><span class="buttontext">Ok</span></a>';
	    }
    	self.template = RichHTML.replaceAll(self.template,"{{buttons}}",buttons);        
    }else {
	    self.hasButtons = true;    
    	self.template = RichHTML.replaceAll(self.template,"{{buttons}}",buttons);    
    }
    return true;

};

RichHTML.window.prototype.render = function() {
	var self = this, $me;
	
	if (self.options.useOverlay) { 
	    $('<div class = "rich-dark-overlay" />').appendTo('body').fadeIn("slow");
	}

	$(document.body).append(self.template);
	$me = $('#'+self.id);	

	if (!self.hasButtons) {		
	    $me.find('.window-buttons').css('display','none');
	    $me.find('.window-description').addClass('window-no-buttons');
	}
	
	if (self.options.hideTitle) {
	    $me.find('.window-title').css('display','none');
	    $me.find('.window-description').addClass('window-no-title');	
	}
	
	self.form = $me.find('.window-description form');
	
	if (typeof (self.options.el) !== "undefined") {
	    RichHTML.debug(3,"Loading content from element with id: "+self.options.el);	
	    $('#'+self.id + ' .window-description form .window-description-elements').html($('#'+self.options.el).html())
	} else if (typeof (self.options.url) !== "undefined") {
	    RichHTML.debug(3,"Loading content from url: "+self.options.url);
	    self.delayLoad = true; //we want to load the data after we draw window
	} else if (typeof (self.options.content) !== "undefined") {
	    RichHTML.debug(3,"Loading content from content param: "+self.options.content);	
	    $('#'+self.id + ' .window-description form .window-description-elements').html(self.options.content)
	}
	
	RichHTML.center($('#'+self.id),window,self.options.transition);
	
	return true;
};

RichHTML.window.prototype.hide = function () {
	var self = this;
	if (self.options.useOverlay) {	    
	    $('.rich-dark-overlay').fadeOut("fast", function() { $(this).remove(); });
    }
    
	$(document).unbind('keydown', self.closeKeyHandler).unbind('keydown', self.tabKeyHandler).unbind('keydown', self.enterKeyHandler);
	$('#'+self.id).remove();
};

RichHTML.window.prototype.validateForm = function () {
	var self = this;

	if(jQuery().validate) {
		self.form.validate({
			highlight: function(element, errorClass, validClass) {			
			    $(element).addClass(errorClass).removeClass(validClass);
			},
			unhighlight: function(element, errorClass, validClass) {
			    $(element).removeClass(errorClass).addClass(validClass);
			    $(element).attr('title','');
			},		
        	errorPlacement: function(error, element) {
                if(error.html() != ''){               
            		element.attr('title',error[0].innerText);
                }
        	}}
        );
		if (self.form.valid()) {
			return true;
		} else {
			$('#'+self.id+' .window-description .error').first().focus();
			return false;
		}
	} else {
		return true;
	}
};

RichHTML.window.prototype.buttonBindings = function () {
	var self = this, $me, data = {};
	$me = $('#'+self.id);

    $me.find('.rich-button').bind('click', function () {
        var scope, buttonId = $(this).attr('id').substring(12);
        
        //lets check to see if we have the default close buttons 
        //because no other buttons were passed
        if (buttonId === "autoclose") {        
	        self.hide();
        	data.btn = "ok";
			$(self).trigger('buttonclick',[data]);	
        } else if (buttonId === "submit") {
	        if (!self.validateForm()) { return false; }        
			self.submit(self.options.onSubmit);
        	data.btn = "submit";
			$(self).trigger('buttonclick',[data]);     	
        } else if (buttonId === "delete") {
			self.callDelete(self.options.onDelete);
        	data.btn = "delete";
			$(self).trigger('buttonclick',[data]);    	
        } else {
        	//validate unless it is a cancel button
	        if ( ( (self.options.buttons[buttonId].type!=="cancel") || typeof (self.options.buttons[buttonId].type) === "undefined") && !self.validateForm()) { 
	        	 return false; 
	       	}
	        if (typeof self.options.buttons[buttonId].onclick === 'function' && 
	        	self.options.buttons[buttonId].onclick != false) {
	            self.options.buttons[buttonId].onclick.apply(self)
	        } else {
	        	self.hide();
	        }
            data.btn = self.options.buttons[buttonId].text; 
			//cancel should not submit trigger for after click
			//so if we haven't defined the btn as canceled or if the type is not canceled trigger the event
			if ((typeof (self.options.buttons[buttonId].type) === "undefined") 
			     	|| (self.options.buttons[buttonId].type !=="cancel") 
			   ) {
	        	$(self).trigger('buttonclick',[data]);
	        }               
        }
		
		
        
        return false
    });

	return true;

};


RichHTML.window.prototype.show = function (options) {
    var self = this, $me;

	if (options && typeof(options.params) !== "undefined") {
		self.params = $.extend(self.params,options.params);
	} else {
		self.params = {};
	}

    RichHTML.debug(3,Array("Starting render for: "+self.id,self));
	if (!self.prepTemplate()) {
		return false;
	}

	if (!self.prepButtons()) {
		return false;
	}

	if (!self.render()) {
		return false;
	}
	
	if (self.hasButtons && !self.buttonBindings()) {
		return false;
	}
	
	$me = $('#'+self.id);
	
	if (self.delayLoad) {
    	RichHTML.onMask(self);
    	$.get(self.options.url, self.params,function(response, status, xhr) {
			  $me.find('.window-description form .window-description-elements').html(response);
			  if (status == "error") {
			    var msg = "Sorry but there was an error: ";
			    RichHTML.debug(1,Array(msg + xhr.status + " " + xhr.statusText,xhr));
			  }
			  self.prepElements(options);
		});
    	RichHTML.onUnMask(self);
    }else{
	    self.prepElements(options);
    }
    
    self.setDraggable();
	$(document).bind('keydown', self.closeKeyHandler).bind('keydown', self.tabKeyHandler).bind('keydown', self.enterKeyHandler);    
};

//this is to prep the content loaded mostly for tabbing
//also adds hidden elements
RichHTML.window.prototype.prepElements = function(options) {
	var self = this, tabbable, $me;
	
	$me = $('#'+self.id);
	//lets set first element active
	$me.find(':input, .rich-button, textarea').eq(0).focus();
    tabbable = $me.find(':input, .rich-button, textarea');			
    if (tabbable.length > 0) {
	    self.elements.firstElement = $(tabbable).filter(':first');
	    self.elements.lastElement = $(tabbable).filter(':last');		
	    self.elements.firstGroup = (self.elements.firstElement[0].type !== 'radio') ?
	        self.elements.firstElement :
	        tabbable.filter("[name='" + self.elements.firstElement[0].name + "']");
	    self.elements.lastGroup = (self.elements.lastElement[0].type !== 'radio') ?
	        self.elements.lastElement :
	        tabbable.filter("[name='" + self.elements.lastElement[0].name + "']");
    }

	//lets add some hidden elements    
	if (options && typeof(options.params) !== "undefined") {
		$.each(options.params,function(c_i, c_val) {
		    $me.find('.window-description form .window-description-elements').append(
		        $('<input/>')
		            .attr('type', 'hidden')
		            .attr('name', c_i)
		            .val(c_val)
		    );
		});
	}
    
};

RichHTML.window.prototype.setDraggable = function () {
    var self = this, $me, relX, relY, thistarget, targetw, targeth,docw,doch,ismousedown=false;

	$me = $('#'+self.id);	
    $me.css('position','absolute');
    thistarget = $me.find('.window-title');
    
    targetw = thistarget.width();
    targeth = thistarget.height()
    
    thistarget.bind('mousedown', function(e){
    	var pos,srcX,srcY,mousePos;
        pos = $me.offset();
        srcX = pos.left;
        srcY = pos.top;

        docw = $('body').width();
        doch = $('body').height();

		mousePos = RichHTML.mouseCoords(e);
        relX = e.pageX - srcX;
        relY = e.pageY - srcY;

        ismousedown = true;
    });

    $(document).bind('mousemove',function(e){ 
    	var maxY, maxX, mousePos, diffX, diffY;
        if(ismousedown)
        {
            targetw = $me.width();
            targeth = $me.height();

            maxX = docw - targetw - 10;
            maxY = doch - targeth - 10;
			
			mousePos = RichHTML.mouseCoords(e);

            diffX = mousePos.x - relX;
            diffY = mousePos.y - relY;

            $me.css('top', (diffY)+'px');
            $me.css('left', (diffX)+'px');
        }
    });

    $(window).bind('mouseup', function(e){
        ismousedown = false;                     
    });

    return this;
};