/**
 * Default Extensions and Observers
 * 
 * @author Kjell Bublitz <kjell@growinthings.de>
 * @copyright (c) 2009, K.Bublitz (Growin'Things)
 * @package js-app
 */

/**
 * TriggerEvent: Simulate Event on Element
 *
 * @todo replace this with $().trigger
 * @param eventName
 * @return event
 */
Element.prototype.triggerEvent = function(eventName) {
    if (document.createEvent) {
        var evt = document.createEvent('HTMLEvents');
        evt.initEvent(eventName, true, true);
        return this.dispatchEvent(evt);
    }
    if (this.fireEvent) {
        return this.fireEvent('on' + eventName);
    }
    return null;
};

/**
 * HTML String to Element (using LowPro)
 * @return element
 */
String.prototype.toDomElement = function() {
    return DOM.Builder.fromHTML(this);
};

/**
 * Element Extensions
 * 
 * @author Kjell Bublitz <kjell@growinthings.de>
 * @copyright (c) 2009, K.Bublitz (Growin'Things)
 * @package js-app
 * @subpackage prototypes
 */
Element.addMethods({
    unwrap: function(element) {
        element = $(element);
        element.up().replace(element);
        return element;
    },
    trigger: function(element, eventName) {
        element = $(element);
        if (document.createEvent) {
            var evt = document.createEvent('HTMLEvents');
            evt.initEvent(eventName, true, true);
            element.dispatchEvent(evt);
        }
        if (this.fireEvent) {
            element.fireEvent('on' + eventName);
        }
        return element;
    },
    click: function(element, func){
    	return $(element).observe('click', func);
    }
});

/**
 * Form Extensions for CakePHP
 * 
 * @author Kjell Bublitz <kjell@growinthings.de>
 * @copyright (c) 2009, K.Bublitz (Growin'Things)
 * @package js-app
 * @subpackage prototypes
 */
Object.extend(Form, {
    clearErrors: function(element) {
        element = $(element);
        element.select('div.error-message').invoke('remove');
        element.select('input.error').invoke('removeClassName', 'error');
    },
    indicatorShow: function(element) {
        element = $(element);
        element.select('.submit-indicator').invoke('show');
    },
    indicatorHide: function(element) {
        element = $(element);
        element.select('.submit-indicator').invoke('hide');
    },
    showErrors: function(model, errorJson) {
        var input,
        key,
        value;

        $H(errorJson.data).each(function(err) {
            key = err.first();
            value = err.last();
            input = $(model + key.split('_').invoke('capitalize').join(''));
            if (input) {
                input.addClassName('error');
                input.up().insert({
                    bottom: '<div class="error-message">' + value + '</div>'
                })
            }
        });
    }
});

/**
 * AppForm class
 * 
 * @author Kjell Bublitz <kjell@growinthings.de>
 * @copyright (c) 2009, K.Bublitz (Growin'Things)
 * @package js-app
 * @subpackage classes
 */
var AppForm = Class.create({
    element: null,
    initialize: function(element, options) {
        this.element = $(element);
        this.options = Object.extend({
            successCallback: Prototype.emptyFunction,
            errorCallback: Prototype.emptyFunction
        },
        options || {});
    }
});


/**
 * ToggleAnchor behavior
 * 
 * links using this are toggling a dom element 
 * Example: (href="#test") would toggle (id="test")
 * 
 * @author Kjell Bublitz <kjell@growinthings.de>
 * @copyright (c) 2009, K.Bublitz (Growin'Things)
 * @package js-app
 * @subpackage behaviors
 */
var ToggleAnchor = Behavior.create({
    initialize: function() {
        this.id = this.element.readAttribute('href').split('#').last();
    },
    onclick: function() {
        new Effect.toggle(this.id, 'blind', {
            duration: 0.3
        });
        return false;
    }
});


/**
 * Flash class for CakePHP
 * 
 * @author Kjell Bublitz <kjell@growinthings.de>
 * @copyright (c) 2009, K.Bublitz (Growin'Things)
 * @package js-app
 * @subpackage classes
 */
var Flash = Class.create({
    element: null,
    to: null,
    options: {
        insertBelow: 'content_main',
        blindDuration: 0.2,
        clickToClose: true,
        className: 'message'
    },
    initialize: function(id, message, options) {
        this.options = Object.extend(this.options, options || {});
        this.id = id;
        this.message = message;
        this.insert();
    },
    insert: function() {
        if (this.id && this.message) {
            if ($$('.message').length) {
              $$('.message').each(function(el){
            	  this.remove(el);
              }.bind(this));
            }
            
            this.element = new Element('div', {
                'class': this.options.className,
                'id': this.id
            }).update(this.message);
            
            var wrapper = this.element.wrap('div');
			wrapper.addClassName('message-fx-wrap');
            wrapper.setStyle({'display': 'none', 'position': 'absolute', 'zIndex': '100', 'overflow': 'hidden', 'height': '39px', 'width': '100%'});

			var lightview = $('lightview');
            if (lightview && lightview.visible()) {
            	this.options.insertBelow = $$('.lv_contentBottom').first();
            }
            
            $(this.options.insertBelow).insert({
                'top': wrapper
            });
            new Effect.BlindDown(wrapper, {duration: this.options.blindDuration});
            
            if (this.id == 'infoMessage') {
            	this.to = window.setTimeout(function(){
            		this.remove(wrapper.down());
            	}.bind(this), 3500);
            }
            
            if (this.options.clickToClose)
            	this.element.observe('click', this.remove.bindAsEventListener(this));
        }
    },
    remove: function(arg) {
    	if (this.to) {
    		window.clearTimeout(this.to);
    	}
    	if (arg.type != undefined) {
    		element = $(arg.element());
    	} else {
    		element = $(arg);
    	}
    	if (element) {
	    	var wrapper = element.up('.message-fx-wrap');
	    	if (wrapper) {
		    	new Effect.BlindUp(wrapper, {
		    		duration: this.options.blindDuration,
		    		afterFinish: function(){
		    			wrapper.remove();
		    		}
		    	});
	    	} else {
	    		element.remove();
	    	}
    	}
    }
});

/**
 * Register global AJAX responder
 */
Ajax.Responders.register({
    onComplete: function(ajax, xhr) {
        if (xhr.responseJSON.messageType) {
			if (xhr.responseJSON.message == 'Yes' || xhr.responseJSON.message == 'No' || xhr.responseJSON.message == 'ok' || xhr.responseJSON.message == 'fail')
				return;
			
            if (xhr.responseJSON.messageType == 'error' && (xhr.responseJSON.message.length)) {
                new Flash('errorMessage', xhr.responseJSON.message)
            }
            if (xhr.responseJSON.messageType == 'success' && (xhr.responseJSON.message.length)) {
                new Flash('successMessage', xhr.responseJSON.message)
            }
            if (xhr.responseJSON.messageType == 'info' && (xhr.responseJSON.message.length)) {
                new Flash('infoMessage', xhr.responseJSON.message)
            }
        }
    }
});


/**
 * Tooltips Class
 *
 * @usage new Tooltips('container');
 * @author Kjell Bublitz <kjell@growinthings.de>
 * @copyright (c) 2009, K.Bublitz (Growin'Things)
 * @package js-app
 * @subpackage classes
 */
var Tooltips = Class.create({
	initialize: function(startElement){
		$$('#'+startElement+' *[title]:not([class=lightview])')
		.invoke('observe', 'mouseover', function(evt){
			var el = $(evt.currentTarget);
			var text = el.getAttribute('title'),
				elPos = el.positionedOffset(),
				elCls = el.classNames(),
				elHeight = el.getHeight(), elWidth = el.getWidth(),
				elLeft = elPos[0], elTop = elPos[1];

			var tip = new Element('div', {
				'class': 'tooltip',
				'style': 'top: 0; left: 0, display: block, visibility: hidden'
			});
			tip.update('<div class="tooltip-inner">'+text+'</div>');

			el.removeAttribute('title');
			el.setAttribute('_title', text);
			el.insert({'after': tip});

			var tipHeight = tip.getHeight(), tipWidth = tip.getWidth();

			if (elCls.include('tip-s')) {
				tip.addClassName('tooltip-south');
				tip.setStyle({
					top: (elTop - elHeight) + 'px',
					left: (elLeft + elWidth / 2 - tipWidth / 2) + 'px'
				});
			}
			else if (elCls.include('tip-e')) {
				tip.addClassName('tooltip-east');
				tip.setStyle({
					top: (elTop + elHeight / 2 - tipHeight / 2) + 'px',
					left: (elLeft - tipWidth) + 'px'
				});
			}
			else if (elCls.include('tip-w')) {
				tip.addClassName('tooltip-west');
				tip.setStyle({
					top: (elTop + elHeight / 2 - tipHeight / 2) + 'px',
					left: (elLeft + elWidth) + 'px'
				});
			}
			else {
				tip.addClassName('tooltip-north');
				tip.setStyle({
					top: (elTop + elHeight) + 'px',
					left: (elLeft + elWidth / 2 - tipWidth / 2) + 'px'
				});
			}

			tip.setStyle({
				visibility: 'visible'
			});
		})
		.invoke('observe', 'mouseout', function(evt){
			var el = $(evt.currentTarget), text = el.getAttribute('_title');
			el.removeAttribute('_title');
			el.setAttribute('title', text);
			$$('div.tooltip').invoke('remove');
		});
	}
});

/**
 * Tabbing Class
 * 
 * @author Kjell Bublitz <kjell@growinthings.de>
 * @copyright (c) 2009, K.Bublitz (Growin'Things)
 * @package js-app
 * @subpackage classes
 */
var SectionTabs = Class.create({
	options: {
		scope: '',
		onChange: function(){return true;},
		onInit: Prototype.emptyFunction
	},
	initialize: function(options) {
		this.options = Object.extend(this.options, options || {});
		this.tabs = $$(this.options.scope + '.tabber-tabs li a');
		this.tabcontents = $$(this.options.scope + '.tabber-tab');
		this.tabs.invoke('observe', 'click', this.click.bindAsEventListener(this));
		this.options.onInit(this.active());
	},
	active: function() {
		var active = this.tabs.filter(function(e){return e.hasClassName('active');});
		if (active.size()) {
			return active.first().readAttribute('href').substr(1);
		}
		return null;
	},
	click: function(evt) {evt.stop();
        var tab = evt.findElement('a'), tabcontent = $(tab.readAttribute('href').substr(1));
        
        if (this.options.onChange(tabcontent.id) == true) {
        
	        this.tabs.invoke('removeClassName', 'active');
	        this.tabcontents.without(tabcontent).invoke('hide');
	
	        if (tab.hasClassName('tab-notoggle')) {
	            tab.addClassName('active');
	            tabcontent.show();
	        } else {
	            if (tabcontent.visible()) {
	                tab.removeClassName('active');
	                tabcontent.hide();
	            } else {
	                tab.addClassName('active');
	                tabcontent.show();
	            }
	        }
        }
	}
});

/**
 * Some functions
 */
var App = {
	addEditor: function(textarea, optin, buynow) {

		var activePlugins = 'basicstyles,buynow,colorbutton,contextmenu,format,font,styles,optin,stylescombo,resize,elementspath,enterkey,entities,filebrowser,find,font,forms,htmldataprocessor,image,indent,justify,keystrokes,link,list,maximize,pastefromword,pastetext,popup,removeformat,scayt,showblocks,table,tabletools,sourcearea,specialchar,tab,templates,toolbar,undo,wysiwygarea,wsc,youtube';
		var activeButtons =  ['Bold','Italic','Underline','Strike', '-', 'NumberedList', 'BulletedList', '-', 'JustifyLeft','JustifyCenter', 'JustifyRight', '-', 'BuyNowButton','OptinButton', '-', 'Image','YouTube','Templates','-','Maximize','RemoveFormat','Source'];

		if (!buynow) {
			activePlugins = 'basicstyles,colorbutton,contextmenu,format,font,styles,optin,stylescombo,resize,elementspath,enterkey,entities,filebrowser,find,font,forms,htmldataprocessor,image,indent,justify,keystrokes,link,list,maximize,pastefromword,pastetext,popup,removeformat,scayt,showblocks,table,tabletools,sourcearea,specialchar,tab,templates,toolbar,undo,wysiwygarea,wsc,youtube';
			activeButtons =  ['Bold','Italic','Underline','Strike', '-', 'NumberedList', 'BulletedList', '-', 'JustifyLeft','JustifyCenter', 'JustifyRight', '-', 'OptinButton', '-', 'Image','YouTube','Templates','-','Maximize','RemoveFormat','Source'];
		}
		
		if (!optin) {
			activePlugins = 'basicstyles,buynow,colorbutton,contextmenu,format,font,styles,stylescombo,resize,elementspath,enterkey,entities,filebrowser,find,font,forms,htmldataprocessor,image,indent,justify,keystrokes,link,list,maximize,pastefromword,pastetext,popup,removeformat,scayt,showblocks,table,tabletools,sourcearea,specialchar,tab,templates,toolbar,undo,wysiwygarea,wsc,youtube';
			activeButtons =  ['Bold','Italic','Underline','Strike', '-', 'NumberedList', 'BulletedList', '-', 'JustifyLeft','JustifyCenter', 'JustifyRight', '-', 'BuyNowButton', '-', 'Image','YouTube','Templates','-','Maximize','RemoveFormat','Source'];
		}

		if (!optin && !buynow) {
			activePlugins = 'basicstyles,colorbutton,contextmenu,format,font,styles,stylescombo,resize,elementspath,enterkey,entities,filebrowser,find,font,forms,htmldataprocessor,image,indent,justify,keystrokes,link,list,maximize,pastefromword,pastetext,popup,removeformat,scayt,showblocks,table,tabletools,sourcearea,specialchar,tab,templates,toolbar,undo,wysiwygarea,wsc,youtube';
			activeButtons = ['Bold','Italic','Underline','Strike', '-', 'NumberedList', 'BulletedList', '-', 'JustifyLeft','JustifyCenter', 'JustifyRight', '-', 'Image','YouTube','Templates','-','Maximize','RemoveFormat','Source'];
		}

	    return CKEDITOR.replace(textarea, {
	        toolbar : 'Basic', uiColor : '#FAFAFA', customConfig : '', baseHref : '', height : 250, width : '99%', resize_maxWidth: '99%',
			plugins : activePlugins,
			toolbar_Basic : [activeButtons, ['Styles','Format','Font','FontSize', 'TextColor', 'Link', 'Unlink']]
	    });
	},
	removeFlash: function(evt) {
		evt.findElement('div').remove();
	},
	selectAll: function(evt) {
		box = evt.element();box.checked = (box.checked ? false : true);
		box.up('table').select('input[type=checkbox]').each(function(e){
			e.checked = (e.checked ? false : true);
		});
	},
	getChecked: function(table) {
		return $(table).select('td input[type=checkbox]').filter(function(e){return e.checked;}).invoke('readAttribute', 'value');
	},
	inlineEditor: function(el, id, url, options) {
				
		return new Ajax.InPlaceEditor(el, base+url+id, Object.extend({
			externalControlOnly: true,
			externalControl: "rename_"+id,
			cancelControl: "button",
			okText: Lang.InlineEdit.okText,
			cancelText: Lang.InlineEdit.cancelText,
			savingText: Lang.InlineEdit.savingText,
			callback: function(form, value) {return "name=" + encodeURIComponent(value)}
		}, options || {}));
	}
};


/**
 * Start Application
 */
document.observe('dom:loaded', function() {
    Event.addBehavior({
        '#content a.toggle': ToggleAnchor,
        '#content .message': function() {
            this.observe('click', App.removeFlash);
        },
        '#content th input.select_all': function() {
        	this.observe('click', App.selectAll);
        }
    });
});


/// MISC FUNCTIONS
function array_merge () {
    // Merges elements from passed arrays into one array
    //
    // version: 1004.1212
    // discuss at: http://phpjs.org/functions/array_merge    // +   original by: Brett Zamir (http://brett-zamir.me)
    // +   bugfixed by: Nate
    // +   input by: josh
    // +   bugfixed by: Brett Zamir (http://brett-zamir.me)
    // *     example 1: arr1 = {"color": "red", 0: 2, 1: 4}    // *     example 1: arr2 = {0: "a", 1: "b", "color": "green", "shape": "trapezoid", 2: 4}
    // *     example 1: array_merge(arr1, arr2)
    // *     returns 1: {"color": "green", 0: 2, 1: 4, 2: "a", 3: "b", "shape": "trapezoid", 4: 4}
    // *     example 2: arr1 = []
    // *     example 2: arr2 = {1: "data"}    // *     example 2: array_merge(arr1, arr2)
    // *     returns 2: {0: "data"}

    var args = Array.prototype.slice.call(arguments),
         retObj = {}, k, j = 0, i = 0, retArr = true;
		 
    for (i=0; i < args.length; i++) {
        if (!(args[i] instanceof Array)) {
            retArr=false;
            break;
		}
    }

    if (retArr) {
        retArr = [];
		for (i=0; i < args.length; i++) {
            retArr = retArr.concat(args[i]);
        }
        return retArr;
    }    var ct = 0;

    for (i=0, ct=0; i < args.length; i++) {
        if (args[i] instanceof Array) {
            for (j=0; j < args[i].length; j++) {
				retObj[ct++] = args[i][j];
            }
        } else {
            for (k in args[i]) {
                if (args[i].hasOwnProperty(k)) {
					if (parseInt(k, 10)+'' === k) {
                        retObj[ct++] = args[i][k];
                    } else {
                        retObj[k] = args[i][k];
                    }                }
            }
        }
    }
    return retObj;
}

