(function($) {
	var spell_context_selector = '#id-spell-context',
		spell_form_title = 'Kontrola pravopisu',
		spell_close_text = '[x]';

	function showSpinner(element) {
		return $('<img class="profesia-spell-working" src="/images/design/ajax-spinner.gif" />').appendTo(element).show();
	}

	function formClick_cb() {
		// hide all suggestions, if any
		$('.profesia-sc-suggestion-box').remove();
	}

	function getModifiedField($field, $dest_element) {
		var old_val = $dest_element.val(),
			tmp_val = old_val,
			offset = 0,
			new_field_value = '',
			$changed = $('span', $field).filter(function(){return $(this).data('misspelled')});

		$changed.each(function() {
			var original_data = $(this).data('misspelled'),
				count = original_data.pos,
				original_len = original_data.word.length;

			tmp_val = tmp_val.substr(0, count+offset)+$(this).text()+old_val.substr(old_val.indexOf(original_data.word)+original_len);
			offset += $(this).text().length - original_len;
		});

		if ($changed.length>0) {
			new_field_value = tmp_val;
		}

		return new_field_value;
	}

$.fn.spellcheck = function(options) {
	return this.each(function() {
		var $this = $(this);
		if ( !$this.is('[type=password]') && !$this.data('spellchecker') ) {
			$this.data('spellchecker', new $.SpellChecker(this, options));
		}

		if (options.useControlPanel!='undefined' && !options.useControlPanel) {
			$this.checkspelling(); // force check after
		}
	});
};

/**
 * Forces a spell check on an element that has an instance of SpellChecker.
 */
$.fn.checkspelling = function() {
	return this.each(function() {
		var spellchecker = $(this).data('spellchecker');
		spellchecker && spellchecker.checkSpelling();
	});
};

$.SpellChecker = function(element, options) {
	this.$element = $(element);
	this.text = '';

	this.$result_elm = null;

	this.options = $.extend({
		lang: 'sk',
		engine: 'pspell',
		url: '/spellcheck/spell_profesia.php',
		ignorecaps: 1,
		ignoredigits: 1,
		useControlPanel: false
	}, options);

	// self object
	var speller = this,
		// create dummy wrapper div element
		wrapper_div = document.createElement('div');

	// wrap input field
	this.$element.wrap(wrapper_div);

	if (this.options.useControlPanel) {

		// generate div to hold spell checker controls
		var a_check = '<a class="profesia-spell-checker-cp-check" title="Kontrola pravopisu">&nbsp;&nbsp;&nbsp;</a>',
			a_resume = '<a class="profesia-spell-checker-cp-resume" title="Späť na editáciu">&nbsp;&nbsp;&nbsp;</a>';

		this.$cp_wrapper = $('<div class="profesia-spell-checker-cp">'+a_check+a_resume+'</div>');
		this.$cp_wrapper.insertBefore(this.$element);

		this.$cp_check_element = $('.profesia-spell-checker-cp-check',this.$cp_wrapper);
		this.$cp_resume_element = $('.profesia-spell-checker-cp-resume',this.$cp_wrapper);
		this.$cp_resume_element.hide();

		this.$cp_check_element.click(function() {
				speller.checkSpelling();
				return false;
			});

		this.$cp_resume_element.click(function(){
				speller._resume();
			});

	} // use ControlPanel
};

$.SpellChecker.prototype = {

	checkSpelling: function() {
		if (this.$result_elm == null) {
			var suggest_element_width = this.$element.outerWidth(false),
				suggest_element_height = this.$element.outerHeight(false);

			this.$result_elm = $('<div class="profesia-spell-checker-result" id="'+this.$element.attr('name')+'"></div>').
				insertAfter(this.$element).width(suggest_element_width).
				height(suggest_element_height);

			this.$result_elm.hide().css({
					'margin-left':this.$element.css('margin-left'),'margin-top':this.$element.css('margin-top'),'margin-right':this.$element.css('margin-right'),'margin-bottom':this.$element.css('margin-bottom')
				});
		}

		var prevText = this.text, text = this.$element.val(), self = this;
		if ( prevText === text ) return;
		this.text = this.$element.val();

		var options = $.extend({ spellText: this.text,action:'spellcheck' }, this.options);
		$.post(this.options.url, options, function(r) { self.spellCheck_cb(r); });
	},

	spellCheck_cb: function(results) {
		var speller = this;

		this._togglePanels();

		if (results) {
			this.$result_elm.html(results);

			// set click function
			$('span', this.$result_elm).addClass('profesia-sc-misspelled profesia-sc-unchecked').click(function() {
				var $current_elm = $(this),
					current_text = $(this).text();

				var data = $current_elm.data('misspelled');
				if (data!='undefined') {
					current_text = data.word;
				}

				var options = $.extend({ suggestionText: current_text, action:'suggest' }, speller.options);
				$.post(speller.options.url, options, function(r) {

					//var $suggestion_box = $('<div>'+r+'</div>').insertAfter($current_elm).addClass('profesia-sc-suggestion-box').css({'position':'absolute','left':$current_elm.position().left,'top':$current_elm.position().top+$current_elm.outerHeight()});
					var $suggestion_box = $(r).insertAfter($current_elm).addClass('profesia-sc-suggestion-box').css({'position':'absolute','left':$current_elm.position().left,'top':$current_elm.position().top+$current_elm.outerHeight()});

					$('li', $suggestion_box).addClass('profesia-sc-suggestion').click(function(){
						$current_elm.text($(this).html()).removeClass('profesia-sc-unchecked').addClass('profesia-sc-corrected');
						$suggestion_box.remove();
						return false;
					});
				});
				return false;

			}).each(function() {
				var current_text = $(this).text(),
					pos = speller.$element.val().indexOf(current_text);

				$(this).data('misspelled', {'word': current_text, 'pos':pos});
			});
		}
		else if (!this.options.useControlPanel) {
			this.$result_elm.html(this.$element.val());
		}

	},

	_resume: function() {
		// remove suggestion box if any
		$('.profesia-sc-suggestion-box', this.$result_elm).remove();

		this.$element.val(this.$result_elm.text());
		this._togglePanels();
	},

	_togglePanels: function () {
		this.$element.toggle();
		this.$result_elm.toggle();
		if (this.options.useControlPanel) {
			this.$cp_check_element.toggle();
			this.$cp_resume_element.toggle();
		}

	}
}

$.fn.spellForm = function(options) {
	function spellFormInternal(options) {
		var string_req = '',
			$speller_fields = $('input[name^=SPELL_FIELD_]:hidden').each(function() {
				var $original = $('[name="'+this.value+'"]'),
					val = $original.val();

				if (val!='undefined' && val) {
					string_req += this.name+'='+encodeURIComponent(val)+'&';
				}
			});

	    options = $.extend({
	    	'useControlPanel':false,
			'filter':spell_context_selector,
			'title':spell_form_title,
			'closeText':spell_close_text,
			'unloadOnHide': true,
			'modal': false,
			'afterShow':function() {
					$('.profesia-spell-working').hide();

					var $context = $(spell_context_selector).click(formClick_cb),
						$boxy = this;

					$('input[id^=id-profesia-spell-button]').click(function() {

						$boxy.hide();

						if (($(this).attr('id') == 'id-profesia-spell-button-submit')) {

				  			var $fields = $('div[id^=SPELL_FIELD_].profesia-spell-checker-result', $context);

			  				$fields.each(function() {
			  					var $this_field = $(this),
			  						name = $this_field.attr('id'),
		  							to_change_name = $('input[name="'+name+'"]').val(),
		  							$dest_element = $('[name="'+to_change_name+'"]');

			  					var new_val = getModifiedField($this_field, $dest_element);

			  					if (new_val) {
			  						$dest_element.val(new_val);
			  					}
			  				});
						}
						return false;
					});

				$('.profesia-spell-field', $context).spellcheck({'useControlPanel':this.options.useControlPanel, 'lang':this.options.lang});
			}
		},options);

		$('input[name^=SPELL_TITLE_]:hidden').each(function(){
			if (this.value!='undefined' && this.value) {
				string_req += this.name+'='+encodeURIComponent(this.value)+'&';
			}
		});

		var btn = $('input[name=SPELL_SUBMIT_BUTTON_TEXT]:hidden').val();
		if (btn) {
			string_req += 'SPELL_SUBMIT_BUTTON_TEXT='+encodeURIComponent(btn)+'&';
		}

		btn = $('input[name=SPELL_CLOSE_BUTTON_TEXT]:hidden').val();
		if (btn) {
			string_req += 'SPELL_CLOSE_BUTTON_TEXT='+encodeURIComponent(btn)+'&';
		}
		if(options.lang && options.lang!='undefined') {
			string_req += 'lang='+options.lang;
		}
		$.post('/spellcheck/spell_profesia_form.php', string_req, function(html){
			new Boxy(html, options);
		});
	}

	return this.each(function() {
		$(this).click(function() {
			showSpinner(this);
			spellFormInternal(options);
			return false;
		});
	});
}

$.fn.spellDetail = function(options) {
	function spellDetailInternal(url_str, options) {
	    options = $.extend({
	    	'useControlPanel':false,
			'filter':spell_context_selector,
			'title':spell_form_title,
		  	'closeText':spell_close_text,
			'unloadOnHide': true,
		  	'modal': false,
		  	'center':true,
	    	'afterShow': function() {
	    		$('.profesia-spell-working').hide();

		  		var $context = $(spell_context_selector).click(formClick_cb);
		  			$boxy=this;

		  		$('input#id-profesia-spell-button-submit').parent('form').submit(function() {
		  			var $form = $(this),
		  				action = this.action,
		  				reload = false;

					$boxy.hide();

		  			var $fields = $('.profesia-spell-checker-result', $form);

		  			$fields.each(function() {
	  					var $this_field = $(this),
	  						name = $this_field.attr('id'),
	  						$dest_element = $('[name="'+name+'"]');

	  					var new_val = getModifiedField($this_field, $dest_element);

	  					// change input element
	  					if (new_val) {
	  						$dest_element.val(new_val);
	  						reload = true;
	  					}
	  				});

		  			// fetch changed form data ...
		  			// ... and post them to script
		  			// speller_submit is required, serialize() function does not include 'submit' inputs
		  			if (reload) {
				  		$.post(action, 'speller_submit=1&'+$form.serialize(), function(response) {
							//redirect to given url
							if ($boxy.options.redirect_script_name) {
								document.location.href = unescape($boxy.options.redirect_script_name);
								//alert(response);
							}
			  			}, 'text');
		  			}
			  		return false;
		  		});

		  		$('input#id-profesia-spell-button-close').click(function() {
		  			$boxy.hide();
		  		});

		  		$('.profesia-spell-field', $context).spellcheck({'useControlPanel':this.options.useControlPanel,'lang':this.options.lang});

	    	}
	    }, options);

	    $.post('/spellcheck/spell_profesia_detail.php', url_str, function(html){
	    	new Boxy(html, options);
	    });
	}

	return this.each(function () {
		$(this).click(function() {
	    	showSpinner(this);
			url_str = this.href.substr(this.href.indexOf('?')+1); //pass all url following ?
	    	spellDetailInternal(url_str,options);
			return false;
		});
	});
}

})(jQuery);