// Ensure that the shadowbox has been loaded before loading our plugin
if(typeof Shadowbox == 'undefined'){
	throw 'Unable to load Shadowbox, which is required for the rich text editor.';
}

// TODO: after 30 minutes clear lock

$.fn.richTextEdit = function(options) {
	
	// Extend our default options with those provided.
  // Note that the first arg to extend is an empty object -
  // this is to keep from overriding our "defaults" object.
  var opts = $.extend({}, $.fn.richTextEdit.defaults, options);
  
  // The cursor position, needed as IE loses the cursor when clicking on other elements
  var caretPos = 0;
	
	// Our plugin implementation code goes here.
	
	// iterate and reformat each matched element
	return this.each(function() {
		var textarea = $(this);
		
		// Only convert textareas
		if (textarea.is('textarea')) {
			
			// build element specific options
      var elementOptions = $.meta ? $.extend({}, opts, $this.data()) : opts;
      
      if (elementOptions.locationUri == undefined) {
      	throw 'Er dient een locatie URI opgegeven te worden';
      }
      else if (elementOptions.categoryUri == undefined) {
      	throw 'Er dient een categorie URI opgegeven te worden';
      }

			// Convert the textarea to an iFrame
      convertToIFrame(textarea, elementOptions);
		}
	});
	
	
	/**
	 * Convert the textarea to an iFrame
	 */
	function convertToIFrame(textarea, elementOptions)
	{
		// Create an iFrame, which will be used to edit the text in
    var iFrame = document.createElement('iframe');
      
    // Copy the element ID
    iFrame.id = textarea.attr('id');
    
		// Add the iFrame after the textarea
    textarea.after(iFrame);
    textarea.hide();
    
    // Check if there is a draft element
    var useDraft = (elementOptions.draftId && confirm("We hebben een niet opgeslagen versie gevonden voor deze pagina.\nWil je verder gaan met deze versie?"));
    
    // If there was a draft but the user has selected to 
    if (elementOptions.draftId && !useDraft) {
    	$.fn.richTextCancel();
    }
    
    // Use the appropriate element's value
    var content = useDraft ? $('#' + elementOptions.draftId).val() : textarea.val();
       
		// Create the source for the iFrame    
    var iFrameSrc = '<html><head><link rel="stylesheet" type="text/css" media="screen, projection" href="/style/reset.css" /><link rel="stylesheet" type="text/css" media="screen, projection" href="/style/style.css" /></head><body id="infoBody">' + content + '</body></html>';
    
    // Initialize the iFrame
    initializeIFrame(iFrame, iFrameSrc, textarea.width(), textarea.height());
    
    // Initialize the menu
    initializeMenu(iFrame, elementOptions);
    
		// Remove the old textarea
  	textarea.remove();
  	
  	// Store drafts at regular interval
  	setInterval('$.fn.richTextStoreDraftCallback(\'' + iFrame.id + '\')', elementOptions.draftInterval);
  	
  	// Set a timeout at which the lock will be removed
  	setTimeout('$.fn.richTextCancel(\'true\')', elementOptions.lockTime)
  	
  	// Set a timeout for the lock time expiry window, which will be displayed
  	// one minute before the lock actually expires
  	var lockExpiredUrl = '/' + elementOptions.locationUri + '/alles-over/lock-verlopen/index.html?srcFrame=' + iFrame.id;
  	setTimeout('$.fn.richTextLockExpiredCallback(\'' + lockExpiredUrl + '\')', elementOptions.lockTime - elementOptions.lockTimeMessageInterval);
	}
	
	
	/**
	 * Initialize the iFrame with the specified source, making it suitable for
	 * directly editing its contents
	 *
	 * @param IFrame iFrame The iFrame to initialize 
	 * @param string iFrameSrc The HTML source to put into the iFrame
	 * @param Textarea textarea The textarea 
	 */
	function initializeIFrame(iFrame, iFrameSrc, width, height)
	{
		iFrame.contentWindow.document.designMode = 'on';
		iFrame.contentWindow.document.open();
		iFrame.contentWindow.document.write(iFrameSrc);
		iFrame.contentWindow.document.close();
		iFrame.contentWindow.focus();
		
		// Make the iFrame have the same dimensions as the textarea
		$(iFrame).width(width);
		$(iFrame).height(height);
	}
	
	
	/**
	 * Initialize the iFrame's menu
	 *
	 * @param IFrame iFrame The iFrame to initialize 
	 * @param array elementOptions An options array
	 */
	function initializeMenu(iFrame, elementOptions)
	{
		var iFrameElement = iFrame;
		
    // Add the correct anchor links
    $('#addTitle').attr('href', '/' + elementOptions.locationUri + '/alles-over/titel-toevoegen/index.html?srcFrame=' + iFrame.id);
    $('#addImage').attr('href', '/' + elementOptions.locationUri + '/alles-over/afbeelding-toevoegen/index.html?srcFrame=' + iFrame.id);
    $('#addLink').attr('href', '/' + elementOptions.locationUri + '/alles-over/link-toevoegen/index.html?srcFrame=' + iFrame.id);
    
    $('#addTitle, #addImage, #addLink').bind('click', function() {
    	iFrameElement.contentWindow.focus();
			
    	// Store the selection for IE browsers
    	if (document.selection) { // If IE
	    	var selRange = iFrameElement.contentWindow.document.selection.createRange(); 	    	
	    	$.fn.richTextEdit.caretPos = Math.abs(selRange.moveStart('character', -1000000));
    	}
    	
    	return true;
		});
    
    $('#cancel').attr('href', '/' + elementOptions.locationUri + '/alles-over/' + elementOptions.categoryUri + '/');
    $('#cancel').bind('click', function() {
  	  if (confirm('Weet u zeker dat u de door u ingevoerde wijzigingen niet wilt opslaan?')) {	    	   
    	  $.fn.richTextCancel();
				return true;
  	  }
  	  
  	  return false;
  	});    
    
    $('#save').bind('click', function() {
    	if (confirm('Weet u zeker dat u de door u ingevoerde wijzigingen wilt opslaan?')) {    	
	    	// Update the content to have it known outside the iFrame
	    	$('#infoContent').val(iFrame.contentWindow.document.body.innerHTML);
	    	
	    	// Submit the form    	
	    	$('#' + elementOptions.formId).submit();	    	
    	}
    	
    	return false;
   	});
    
   	$('#example').bind('click', function() {   		
   		// Determine the content
   		var content = iFrame.contentWindow.document.body.innerHTML;
   		var anchor = $(this);
   		
   		// Store the latest version   		
    	$.fn.richTextStoreDraft(content, function(contentId) {
				
    		// After storing the draft, we can determine the URL to view the preview				    		
    		var url = '/' + elementOptions.locationUri + '/alles-over/' + elementOptions.categoryUri + '/voorbeeld/?contentId=' + contentId;
    		
    		// Open a shadowbox to preview the contents
    		Shadowbox.open({
    			title:  'Voorbeeld bekijken',
	        type:   'iframe',
	        content: url
    		});
    	});

    	return false;
    });
    
    // Add the menu both before and after the iFrame    
    $('div.menu').show()
	}
};


/**
 * Called when the lock expires
 */
$.fn.richTextCancel = function(onlyRemoveLock)
{
	var locationUri = $("#locationUri").val();
	var infoForm = $("#info");
	var params = infoForm.serializeArray();
	
	// By default, we also remove the lock
	if (onlyRemoveLock == undefined) {
		onlyRemoveLock = false;
	}
	
	// Indicate if we should only remove the lock
	params[params.length] = {name: 'lockOnly', value: onlyRemoveLock};
	
	$.post('/' + locationUri + '/alles-over/annuleren/', params);
}


/**
 * Called when the lock expires
 */
$.fn.richTextLockExpiredCallback = function(url)
{
	// Open a shadowbox to preview the contents
	Shadowbox.open({
		title:  'Deblokkeren',
    type:   'iframe',
    content: url
	});
}


/**
 * Store a draft version
 *
 * @param string iFrameId The ID of the iFrame which contents need to be saved
 */
$.fn.richTextStoreDraftCallback = function(iFrameId) {
	var iFrame = document.getElementById(iFrameId);	
	
	// Store the draft using the current iFrame's inner HTML
	$.fn.richTextStoreDraft(iFrame.contentWindow.document.body.innerHTML);
};


/**
 * Store a draft version
 *
 * @param string content The content to store as a draft
 * @param callback callback The function to call when the post completed
 */
$.fn.richTextStoreDraft = function(content, callback) {
	// Update the content to have it known outside the iFrame
  $('#infoContent').val(content);
	
  var infoForm = $('#info');
  
  // Post the form
  $.ajax({
	  type: 'POST',
	  dataType: 'json',
	  url:  infoForm.attr('action'),
	  data: infoForm.serializeArray(),
	  success: function(contentId) {
	  	if (callback != undefined) {
	  		callback(contentId);
	  	}
	  }
	});
};


/**
 * Add an image
 *
 * @param string url The URL of the image
 * @param string thumbUrl The URL of the image thumb
 * @param string description The image title
 */
$.fn.richTextAddImage = function(url, thumbUrl, description) {
	// Loop through all elements
	return $(this).each(function() {
				
		// Only support iframes
		if ($(this).is('iframe')) {
			$.fn.richTextInsertHtml(this.contentWindow, '<a href="' + url + '" rel="shadowbox" title="' + description + '"><img src="' + thumbUrl + '" alt="' + description + '" title="' + description + '" /></a>');
		}
	});
};


/**
 * Add a link
 *
 * @param string url The URL to which the link points
 * @param string description The link text
 */
$.fn.richTextAddLink = function(url, description) {
	// Loop through all elements
	return $(this).each(function() {
		
		// Ensure that the URL is prefixed with http:// to prevent links from being
		// treated as site references instead of external references
		if (url.substr(0, 7).toLowerCase() != 'http://') {
			url = 'http://' + url;
		}		
		
		// Only support iframes
		if ($(this).is('iframe')) {
			var internalRegexp = new RegExp('http://.*?' + location.hostname + '/');
			var internal = internalRegexp.test(url);			
			
			var anchorHTML = '<a href="' + url + '"' + (internal ? '' : ' rel="external"') +  '>' + description + '</a>'								
			$.fn.richTextInsertHtml(this.contentWindow, anchorHTML);			
		}
	});
};


/**
 * Add a title
 *
 * @param string title The header title
 */
$.fn.richTextAddTitle = function(title) {
	// Loop through all elements
	return $(this).each(function() {
				
		// Only support iframes
		if ($(this).is('iframe')) {
			$.fn.richTextInsertHtml(this.contentWindow, '<h3>' + title + '</h3>')
		}
	});
};

/**
 * Insert HTML into the content window
 */
$.fn.richTextInsertHtml = function(contentWindow, html)
{
	// Focus on the content window
	contentWindow.focus();
	
	if (window.getSelection) { //Gecko		
    contentWindow.document.execCommand('insertHTML', false, html);
  }
  else if (document.selection) { //IE    
  	// Restore the cursor position
    var selRange = contentWindow.document.selection.createRange();    
		selRange.collapse(true);
		selRange.move('character', $.fn.richTextEdit.caretPos);
		selRange.select();
    selRange.pasteHTML(html);
  }
  
  contentWindow.focus();
}


// Set-up the plugin defaults
$.fn.richTextEdit.defaults = {
  locationUri:   null,
  categoryUri:   null,
  draftId:       null,
  formId:        'info',  
  draftInterval: 1000 * 60 * 5,  // The interval at which drafts are stored
  lockTime:      1000 * 60 * 30, // The maximum time the user can hold the lock
  lockTimeMessageInterval: 1000 * 60
};