// TODO - Gradually transitioning to using a namespace

if (typeof KIFFETS == 'undefined' || !KIFFETS) {
  // Defines the KIFFETS.core module
  var KIFFETS = 
    (function($) {
       this.core =
	 (function() {
	    ///////////////////////////////////////////////////////////
	    // Usage IEprompt("dialog descriptive text", "default starting value");
	    // 
	    // IEprompt will call promptCallback(val)
	    // Where val is the user's input or null if the dialog was canceled.
	    ///////////////////////////////////////////////////////////

	    ///////////////////////////////////////////////////////////
	    // This source code has been released into the public domain
	    // January 14th, 2007.
	    // You may use it and modify it freely without compensation
	    // and without the need to tell everyone where you got it.
	    ///////////////////////////////////////////////////////////


	    ///////////////////////////////////////////////////////////
	    // You must create a promptCallback(val) function to handle
	    // the user input.  If you don't this script will fail and
	    // Bunnies will die.
	    ///////////////////////////////////////////////////////////


	    ///////////////////////////////////////////////////////////
	    // These are global scope variables, they should remain global.
	    ///////////////////////////////////////////////////////////
	    var _dialogPromptID=null;
	    var _blackoutPromptID=null;
	    ///////////////////////////////////////////////////////////

	    this.iePrompt = function(innertxt, callback, def) {

	      var that=this;

	      // Check to see if this is MSIE 7.   This isn't a great general purpose
	      // detection system but it works well enough just to find MSIE 7.
	      var _isIE7=(navigator.userAgent.indexOf('MSIE 7')>0);

	      this.wrapupPrompt = function (cancled) {
		// wrapupPrompt is called when the user enters or cancels the box.
		// It's called only by the IE7 dialog box, not the non IE prompt box
		if (_isIE7) {
		  // Make sure we're in IE7 mode and get the text box value
		  var val=document.getElementById('iepromptfield').value;
		  // clear out the dialog box
		  _dialogPromptID.style.display='none';
		  // clear out the screen
		  _blackoutPromptID.style.display='none';
		  // clear out the text field
		  document.getElementById('iepromptfield').value = '';
		  // if the cancel button was pushed, force value to null.
		  if (cancled) { val = '' }
		  // call the user's function
		  callback(val);
		}
		return false;
	      };

	      //if def wasn't actually passed, initialize it to null
	      if (def==undefined) { def=''; }

	      if (_isIE7) {
		// If this is MSIE 7.0 then...
		if (_dialogPromptID==null) {
		  // Check to see if we've created the dialog divisions.
		  // This block sets up the divisons
		  // Get the body tag in the dom
		  var tbody = document.getElementsByTagName("body")[0];
		  // create a new division
		  var tnode = document.createElement('div');
		  // name it
		  tnode.id='IEPromptBox';
		  // attach the new division to the body tag
		  tbody.appendChild(tnode);
		  // and save the element reference in a global variable
		  _dialogPromptID=document.getElementById('IEPromptBox');
		  // Create a new division (blackout)
		  tnode = document.createElement('div');
		  // name it.
		  tnode.id='promptBlackout';
		  // attach it to body.
		  tbody.appendChild(tnode);
		  // And get the element reference
		  _blackoutPromptID=document.getElementById('promptBlackout');
		  // assign the styles to the blackout division.
		  _blackoutPromptID.style.opacity='.9';
		  _blackoutPromptID.style.position='absolute';
		  _blackoutPromptID.style.top='0px';
		  _blackoutPromptID.style.left='0px';
		  _blackoutPromptID.style.backgroundColor='#555555';
		  _blackoutPromptID.style.filter='alpha(opacity=90)';
		  _blackoutPromptID.style.height=(document.body.offsetHeight<screen.height) ? screen.height+'px' : document.body.offsetHeight+20+'px'; 
		  _blackoutPromptID.style.display='block';
		  _blackoutPromptID.style.zIndex='50';
		  // assign the styles to the dialog box
		  _dialogPromptID.style.border='2px solid blue';
		  _dialogPromptID.style.backgroundColor='#DDDDDD';
		  _dialogPromptID.style.position='absolute';
		  _dialogPromptID.style.width='330px';
		  _dialogPromptID.style.zIndex='100';
		}
		// This is the HTML which makes up the dialog box, it will be inserted into
		// innerHTML later. We insert into a temporary variable because
		// it's very, very slow doing multiple innerHTML injections, it's much
		// more efficient to use a variable and then do one LARGE injection.
		var tmp = '<div style="width: 100%; background-color: blue; color: white; font-family: verdana; font-size: 10pt; font-weight: bold; height: 20px">Input Required</div>';
		tmp += '<div style="padding: 10px">'+innertxt + '<BR><BR>';
		tmp += '<form action="" onsubmit="return that.wrapupPrompt()">';
		tmp += '<input id="iepromptfield" name="iepromptdata" type=text size=46 value="'+def+'">';
		tmp += '<br><br><center>';
		tmp += '<input type="submit" value="&nbsp;&nbsp;&nbsp;OK&nbsp;&nbsp;&nbsp;">';
		tmp += '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
		tmp += '<input type="button" onclick="that.wrapupPrompt(true)" value="&nbsp;Cancel&nbsp;">';
		tmp += '</form></div>';
		// Stretch the blackout division to fill the entire document
		// and make it visible.  Because it has a high z-index it should
		// make all other elements on the page unclickable.
		_blackoutPromptID.style.height=(document.body.offsetHeight<screen.height) ? screen.height+'px' : document.body.offsetHeight+20+'px'; 
		_blackoutPromptID.style.width='100%';
		_blackoutPromptID.style.display='block';
		// Insert the tmp HTML string into the dialog box.
		// Then position the dialog box on the screen and make it visible.
		_dialogPromptID.innerHTML=tmp;
		_dialogPromptID.style.top=parseInt(document.documentElement.scrollTop+(screen.height/3))+'px';
		_dialogPromptID.style.left=parseInt((document.body.offsetWidth-315)/2)+'px';
		_dialogPromptID.style.display='block';
		// Give the dialog box's input field the focus.
		document.getElementById('iepromptfield').focus();
	      } else {
		// we are not using IE7 so do things "normally"
		callback(prompt(innertxt,def));
	      }
	    };

	    return this;
	  })();
       
       return this;
     })(jQuery);
  

}

/**
 * Toggle the specified element from display: block to display: none.
 * Also optionally updates the text of the specified toggleID element to
 * reflect whether the item is showing
 */ 
function elementToggle(elID, toggleID, immediate) {
  var isShowing = false;
  if ($('#'+elID).css('display') == 'block') {
    isShowing = false;
    if (immediate) {
      $('#'+elID).hide();
    } else {
      $('#'+elID).slideUp();
    }
  } else {
    isShowing = true;
    if (immediate) {
      $('#'+elID).show();
    } else {
      $('#'+elID).slideDown();
    }
  }

  if (toggleID) {
    if (isShowing) {
      $('#'+toggleID).text('-');
    } else {
      $('#'+toggleID).text('+');
    }
  }
}

/**
 * Encode fragment components in a way that we can have & as separator between components and 
 * still support special characters within the component
 */
function encodeFragmentComponent(comp) {
  var encoded = encodeURIComponent(comp);
  return encoded;
}

/**
 * Remove the comments from the specified json string
 */
function stripComments(commentedJSON) {
  var uncommented = commentedJSON;
  if (commentedJSON.indexOf('/*') == 0 &&
      commentedJSON.lastIndexOf('*/') == commentedJSON.length-2) {
    uncommented = commentedJSON.substring(2,commentedJSON.length-2);
  }
  return uncommented;
}

/**
 * Is the specified email string reasonable - 
 *   with some very simple verification
 */
function isEmailReasonable(emailStr) {
  var MIN_EMAIL_LENGTH = 4;
  var atPos = (emailStr != null) ? emailStr.indexOf('@') : -1;
  var secondAt = (emailStr != null) ? emailStr.indexOf('@', atPos + 1) : -1;

  return (emailStr && emailStr.length > MIN_EMAIL_LENGTH && secondAt == -1 &&
          atPos > 0 && atPos < emailStr.length-2);
}


function setupLoginForm(formID, alertID, redirectURL) {
	    // These are the options passed to setup the login form
	    var lFormOpts = {
	      url: '/loginAjax/',
	      beforeSubmit: function(formData, jqForm, options) {
            var username = null;
            var password = null;

            // TODO - Better form validation
            for (i in formData) {
              if (formData[i].name == 'username') {
                username = formData[i].value;
              } else if (formData[i].name == 'password') {
                password = formData[i].value;
              }
            }           
                  
            if (username.length > 0 &&
                password.length > 0) {
              return true;
            } else {
              $('#'+alertID).css('display','block');
              $('#'+alertID).text('You must specify both username and password.');
              return false;
            }
	      },
	      success: function(responseTxt, statusTxt) {
            var result = JSON.parse(stripComments(responseTxt));
            if (result['result'] == 'success') {
              if (redirectURL) {
                top.location = redirectURL;
              } else {
                location.reload();
              }
            } else {
              $('#'+alertID).css('display','block');
              $('#'+alertID).text('The username or password is not valid.');
            }
	      },
	      type: 'post'
	    };
              
	    $('#'+formID).ajaxForm(lFormOpts);  
}

function setupRegisterForm(formID, alertID, redirectURL, submitURL) {
	    var MIN_USERNAME_LENGTH = 3;
	    var MIN_PASSWORD_LENGTH = 6;

        var regURL = '/register/';
        if (submitURL) {
          regURL = submitURL;
        }

	    // These are the options passed to setup the register form
	    var rFormOpts = {
	      url: regURL,
	      beforeSubmit: function(formData, jqForm, options) {
		var usernameReasonable = false;
		var emailReasonable = false;
		var password1 = null;
		var password2 = null;

		// TODO - Better form validation
		for (i in formData) {
		  if (formData[i].name == 'username') {
		    var username = formData[i].value;
		    if (username.length >= MIN_USERNAME_LENGTH &&
			username.indexOf('@') == -1) {
		      // Note that we don't allow @'s in the username since
		      // then we can't differentiate emails
		      usernameReasonable = true;
		    }
		  }
		  else if (formData[i].name== 'email') {
		    var email = formData[i].value;
		    if (isEmailReasonable(email)) {
		      // We use length-2 because the min domain string is 2
		      emailReasonable = true;
		    }
		  }
		  else if (formData[i].name == 'password1') {
		    password1 = formData[i].value;
		  }
		  else if (formData[i].name == 'password2') {
		    password2 = formData[i].value;
		  }
		}                  

		if (emailReasonable &&
		    usernameReasonable &&
		    password1.length >= MIN_PASSWORD_LENGTH &&
		    password1 == password2) {

		  return true;
		}             
		else {
		  if (!usernameReasonable) {
		    $('#'+alertID).css('display','block');
		    $('#'+alertID).text('Username must be at least '+MIN_USERNAME_LENGTH+' characters and cannot contain the @ symbol.');
		  } else if (password1.length < MIN_PASSWORD_LENGTH) {
		    $('#'+alertID).css('display','block');
		    $('#'+alertID).text('Password must be at least '+MIN_PASSWORD_LENGTH+' characters');
		  } else if (password1 != password2) {
		    $('#'+alertID).css('display','block');
		    $('#'+alertID).text('Your passwords do not match');
		  } else if (!emailReasonable) {
		    $('#'+alertID).css('display','block');
		    $('#'+alertID).text('You must enter a valid email address.');
		  }

		  return false;
		}
	      },
	      success: function(responseTxt, statusTxt) {
		var result = JSON.parse(stripComments(responseTxt));
		if (result['result'] == 'success') {
          if (redirectURL) {
            top.location = redirectURL;
          } else {
            location.reload();
          }
		} 
		else {
		  $('#'+alertID).css('display','block');
		  $('#'+alertID).text(result['message']);
		}
	      },
	      type: 'post'
	    };            
	    $('#'+formID).ajaxForm(rFormOpts);
}

// Loads CSS as needed, if it's already been loaded, then it isn't loaded again
function loadCSS(href) {
  var bodyEl = $('body');
  
  if (!bodyEl.data('loaded::'+href)) {
    bodyEl.data('loaded::'+href, true);
    
    var linkEl=document.createElement("link");
    linkEl.setAttribute("rel", "stylesheet");
    linkEl.setAttribute("type", "text/css");
    linkEl.setAttribute("href", href);
    document.getElementsByTagName("head")[0].appendChild(linkEl);
  }
}


// Loads JS as needed, if it's already been loaded, then it isn't loaded again
function loadJS(href, callback) {
  var bodyEl = $('body');
  
  if (!bodyEl.data('loaded::'+href)) {
    bodyEl.data('loaded::'+href, true);

    // Load this javascript manually with cache=true, because otherwise Yahoo's servers get confused - this only applies to "combo" requests
    var shouldCache = (href.indexOf('yui.yahooapis.com') != -1 && 
                       href.indexOf('combo?') != -1);

    jQuery.ajax({
      url: href,
          async: false,
          cache: shouldCache,
          dataType: "script",
          success: callback
          });
  } else {
    callback();
  }
}

