/**
 * Core Design Captcha plugin for Joomla! 1.5
 * @author		Daniel Rataj, <info@greatjoomla.com>
 * @package		Joomla 
 * @subpackage	System
 * @category	Plugin
 * @version		1.0.0 Experimental
 * @copyright	Copyright (C) 2007 - 2010 Great Joomla!, http://www.greatjoomla.com
 * @license		http://www.gnu.org/copyleft/gpl.html GNU/GPL 3
 * 
 * This file is part of Great Joomla! extension.   
 * This extension is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This extension is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

if (typeof(jQuery) === 'function') {
	
	(function($) {
		
		$.fn.cdcaptcha = function(options) {

			// set defaults
			var defaults = {
				submitElement : 'input[type="submit"]',
				prependElement: '',
				position : 'before',
				scriptDeclaration : '',
				scope : '',
				uitheme : 'ui-lightness',
				random : '',
				additionalBoxStyle : '',
				autoFormSubmit : false,
				rememberFields : {},
				slideCaptchaUp : 500,
				headerText : 'Captcha',
				infoText : 'Proves you\'re human and slide to unlock.',
				lockedText : 'Locked',
				unlockedText : 'Unlocked',
				inputValue: 1,
				saltValue: 9,
				checkValue: 10
			},
			opts = $.extend(defaults, options);
			
			if (typeof($.fn.cdcaptcha.globalDefaults) === 'object') {
				opts = $.extend(opts, $.fn.cdcaptcha.globalDefaults);
			}
			
			return this.each(function() {
				
				if (!opts.random) return false;
				
				// check defaults
				opts.submitElement = opts.submitElement || 'input[type="submit"]';
				opts.prependElement = opts.prependElement || opts.submitElement;
				opts.position = opts.position || 'before';
				
				var form = $(this),
				captcha_container = {},
				submitElement = $(opts.submitElement, form),
				prependElement = $(opts.prependElement, form),
				captcha_tmpl =
				'<div id="cdcaptcha"'+ (opts.additionalBoxStyle ? ' style="' + opts.additionalBoxStyle + '"' : '') +'>' + 
					'<div class="' + opts.uitheme + '">' +
						'<div class="ui-widget ui-widget-content ui-corner-all cdcaptcha_content">' + 
							'<div class="captcha_header">' + opts.headerText + '</div>' +
							'<div class="infotext">' + opts.infoText + '</div>' +
							'<div class="slider"></div>' +
							'<div class="cleaner" />' +
							'<div class="status">' +
								'<div class="status_locked active"><span class="icon_active" />' + opts.lockedText + '</div>' +
								'<div class="status_unlocked"><span class="icon_inactive" />' + opts.unlockedText + '</div>' +
								'<div class="cleaner" />' +
							'</div>' +
							'<input type="hidden" name="cdcaptcha_' + opts.scope + '" value="0" />' +
						'</div>' + 
					'</div>' +
					'<div class="poweredby">Captcha by <a href="http://www.greatjoomla.com/" target="_blank" title="Great Joomla!">Great Joomla!</a></div>' +
				'</div>';
				
				// remember fields routine
				if ($.fn.cdcaptcha.empty(opts.rememberFields) === false && typeof(opts.rememberFields) === 'object') {
					$.each(opts.rememberFields, function(el, val) {
						var find_el = form.find('[name="' + el + '"]');
						form.find('[name="' + el + '"]').val(val);
					});
				}
				
				if (opts.position === 'before') {
					prependElement.before(captcha_tmpl);
					captcha_container = prependElement.prev('#cdcaptcha');
				} else {
					prependElement.after(captcha_tmpl);
					captcha_container = prependElement.next('#cdcaptcha');
				}
				
				// prevent non button submit elements
				var isFormButton = false;
				if(submitElement.is('button') || submitElement.is('input')) {
					isFormButton = true;	
				}
				
				if (isFormButton) {
					// disable submit button
					submitElement.attr('disabled', 'disabled');
				}
				
				var cdcaptcha_input = $('input:hidden[name="cdcaptcha_' + opts.scope + '"]', form),
				locked = $('.status .status_locked', form),
				unlocked = $('.status .status_unlocked', form);
				
				var captcha_enabled = false;
				
				// slider functionality
				$(".slider", form).slider({
					animate: true,
					value: 0,
					max: opts.inputValue,
					step: opts.inputValue / 4,
					range: 'min',
					stop: function(event, ui) {
						
						// set value of usercheck
						cdcaptcha_input.val(ui.value + opts.saltValue);
						
						// enable submit button
						if(cdcaptcha_input.val() == opts.checkValue) {
							// enable
							if (isFormButton) {
								submitElement.attr('disabled', '');
								
								// // UI buttons routine
								$.fn.cdcaptcha.uiButtonsRoutine(submitElement);
							}
							cdcaptcha_input.val(opts.random);
							
							locked.removeClass('active').children('span').removeClass('icon_active').addClass('icon_inactive');
							unlocked.addClass('active').children('span').removeClass('icon_inactive').addClass('icon_active');
							
							captcha_container.css({
								border : 'none'
							});
							
							captcha_enabled = true;
							
							// form autosubmit
							if (opts.autoFormSubmit === true) {
								// must be "click" not "submit"
								submitElement.click();
							}
							
							// slide captcha element up if required
							if (opts.slideCaptchaUp != 0) {
								captcha_container.slideUp(opts.slideCaptchaUp);
							}
							
						} else{
							// disable
							if (isFormButton) {
								submitElement.attr('disabled', 'disabled');
								
								// UI buttons routine
								$.fn.cdcaptcha.uiButtonsRoutine(submitElement);
							}
							cdcaptcha_input.val(0);
							
							locked.addClass('active').children('span').removeClass('icon_inactive').addClass('icon_active');
							unlocked.removeClass('active').children('span').removeClass('icon_active').addClass('icon_inactive');
							
							captcha_enabled = false;
						}

					}
				});
				
				// prevent submit if captcha not enabled
				form.submit(function(e) {
					
					if (captcha_enabled === true) return true;
					
					captcha_container.animate({
						    border : '2px solid red'
						  }, 150);
					
					e.preventDefault();
					return false;
				});
				
				// call function if set and at last!!!
				if (typeof(opts.scriptDeclaration) === 'function') {
					opts.scriptDeclaration(form, captcha_container);
				}
				
			});
		};
		
		$.fn.cdcaptcha.empty = function(mixed_var) {
		    // http://kevin.vanzonneveld.net
		    // +   original by: Philippe Baumann
		    // +      input by: Onno Marsman
		    // +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
		    // +      input by: LH
		    // +   improved by: Onno Marsman
		    // +   improved by: Francesco
		    // +   improved by: Marc Jansen
		    // +   input by: Stoyan Kyosev (http://www.svest.org/)
		    // *     example 1: empty(null);
		    // *     returns 1: true
		    // *     example 2: empty(undefined);
		    // *     returns 2: true
		    // *     example 3: empty([]);
		    // *     returns 3: true
		    // *     example 4: empty({});
		    // *     returns 4: true
		    // *     example 5: empty({'aFunc' : function () { alert('humpty'); } });
		    // *     returns 5: false

		    var key;
		    
		    if (mixed_var === "" ||
		        mixed_var === 0 ||
		        mixed_var === "0" ||
		        mixed_var === null ||
		        mixed_var === false ||
		        typeof mixed_var === 'undefined'
		    ){
		        return true;
		    }

		    if (typeof mixed_var == 'object') {
		        for (key in mixed_var) {
		            return false;
		        }
		        return true;
		    }

		    return false;
		};
		
		$.fn.cdcaptcha.strpos = function(haystack, needle, offset) {
		    // http://kevin.vanzonneveld.net
		    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
		    // +   improved by: Onno Marsman    
		    // +   bugfixed by: Daniel Esteban
		    // +   improved by: Brett Zamir (http://brett-zamir.me)
		    // *     example 1: strpos('Kevin van Zonneveld', 'e', 5);
		    // *     returns 1: 14

		    var i = (haystack+'').indexOf(needle, (offset || 0));
		    return i === -1 ? false : i;
		};
		
		$.fn.cdcaptcha.str_replace = function (search, replace, subject, count) {
		    // http://kevin.vanzonneveld.net
		    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
		    // +   improved by: Gabriel Paderni
		    // +   improved by: Philip Peterson
		    // +   improved by: Simon Willison (http://simonwillison.net)
		    // +    revised by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
		    // +   bugfixed by: Anton Ongson
		    // +      input by: Onno Marsman
		    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
		    // +    tweaked by: Onno Marsman
		    // +      input by: Brett Zamir (http://brett-zamir.me)
		    // +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
		    // +   input by: Oleg Eremeev
		    // +   improved by: Brett Zamir (http://brett-zamir.me)
		    // +   bugfixed by: Oleg Eremeev
		    // %          note 1: The count parameter must be passed as a string in order
		    // %          note 1:  to find a global variable in which the result will be given
		    // *     example 1: str_replace(' ', '.', 'Kevin van Zonneveld');
		    // *     returns 1: 'Kevin.van.Zonneveld'
		    // *     example 2: str_replace(['{name}', 'l'], ['hello', 'm'], '{name}, lars');
		    // *     returns 2: 'hemmo, mars'

		    var i = 0, j = 0, temp = '', repl = '', sl = 0, fl = 0,
		            f = [].concat(search),
		            r = [].concat(replace),
		            s = subject,
		            ra = r instanceof Array, sa = s instanceof Array;
		    s = [].concat(s);
		    if (count) {
		        this.window[count] = 0;
		    }

		    for (i=0, sl=s.length; i < sl; i++) {
		        if (s[i] === '') {
		            continue;
		        }
		        for (j=0, fl=f.length; j < fl; j++) {
		            temp = s[i]+'';
		            repl = ra ? (r[j] !== undefined ? r[j] : '') : r[0];
		            s[i] = (temp).split(f[j]).join(repl);
		            if (count && s[i] !== temp) {
		                this.window[count] += (temp.length-s[i].length)/f[j].length;}
		        }
		    }
		    return sa ? s : s[0];
		};
		
		/**
		 * Manage UI buttons
		 * 
		 * @param		submitElement
		 * @return		void
		 */
		$.fn.cdcaptcha.uiButtonsRoutine = function(submitElement) {
			
			var state = submitElement.is(':disabled') ? 0 : 1;
			
			switch(state) {
				case 0:
					submitElement.button('disable');
					break;
				case 1:
					submitElement.button('enable');
					break;
			}
			
		};
		
		// Add new jQuery expression
		$.expr[':'].nextToLast = function(obj, ind, prop, node){

		     // if ind is 2 less than the length of the array of nodes, keep it
		     if (ind == node.length-2) {
		          return true;
		     } else {
		          // else, remove the node
		          return false;
		     }
		};
		
	})(jQuery);
} else {
	alert('Core Design Captcha plugin:\n- Missing jQuery JS!');
}
