/*
utils.js.php

Copyright (c) Gareth Hadfield 2008
*/


// utils

var DEBUG_MODE = true;

var IMAGE_FILES = ["jpg", "png", "gif", "jpeg", "bmp"];

function image_file_mask(){
  var result = new Array();
  for(var i=0; i<IMAGE_FILES.length; i++){
    result[i] = "*."+IMAGE_FILES[i];
  }
  return(result.join("|"));
}



function assert(aCondition, aMessage){
  if(DEBUG_MODE){

    if(aCondition == undefined){
      assert(false);
    }
    else{
      if(typeof(aCondition) == "string"){
        if(aMessage == undefined){
          aMessage = aCondition;
        }
        aCondition = eval(aCondition);
      }

      if(!aCondition){
        if(aMessage == undefined){
          aMessage = "";
        }
        alert("Assertion Failure (" + aMessage + ")");
      }
    }

  }
}

function debug(aString){
  // pop open a debug window and dump debug info (aString) as text lines
  // use this in preference to alert in loops
  if(DEBUG_MODE && (popup_text_editor != undefined) && (window.IN_DEBUG_FUNCTION==undefined)){
    window.IN_DEBUG_FUNCTION="IN_DEBUG_FUNCTION";
    if(document.opendotsGlobalDebugWindow == undefined){
      document.opendotsGlobalDebugWindow = popup_text_editor("", undefined, "Debug Messages");
      document.opendotsGlobalDebugWindow.freeOnClose = false;
      var aMainToolbar = document.opendotsGlobalDebugWindow.getToolbarGroup("main");
      var aButton = aMainToolbar.addToolbarButton("Clear",
        bind(document.opendotsGlobalDebugWindow, function(){this.clear();}),
        "/opendots/themes/Donald/clear_button.gif", "/opendots/themes/Donald/clear_button_highlight.gif");
    }

    document.opendotsGlobalDebugWindow.text_editor.value += aString + "\n";
    document.opendotsGlobalDebugWindow.show();
    window.IN_DEBUG_FUNCTION=undefined;
  }
}

function bind(aContext, aFunction){
  assert(aContext != undefined, "bind(aContext, aFunction) \naContext cannot be undefined. \n\nContext=\n"+aContext+" \n\naFunction=\n"+aFunction);
  assert(aFunction != undefined, "bind(aContext, aFunction) \naFunction cannot be undefined. \n\nContext=\n"+aContext+" \n\naFunction=\n"+aFunction);

  return(function(){
    return aFunction.apply(aContext, arguments);
  });
}

function chain(aFunction1, aFunction2){
  return(function(){
    var result;
    if((aFunction1 != undefined) && (aFunction1 != "")){
      result = aFunction1.apply(this, arguments);
    }
    if((aFunction2 != undefined) && (aFunction2 != "")){
      result = aFunction2.apply(this, arguments);
    }
    return(result);
  });
}

function exec_scripts(aElement){
  // find and eval (execute) all scripts within aElement
  assert(aElement != undefined, "exec_scripts(aElement) aElement cannot be undefined");

  // keep a pointer to the old write functions
  var oldWrite = document.write;
  var oldWriteln = document.writeln;

  // redefine document write functions to catch the output as a string
  var outputText = "";

  document.write = function(){
    for(var i=0; i<arguments.length; i++){
      outputText += arguments[i];
    }
  };

  document.writeln = function(){
    for(var i=0; i<arguments.length; i++){
      outputText += arguments[i] + "\n";
    }
  };

  var aScripts = all_tags("script", aElement);

  if(aScripts != undefined){

    for(var i=0; i<aScripts.length; i++){
      outputText = "";
      var aScript = aScripts[i];
      var aScriptText = aScript.innerHTML;
      eval(aScriptText);
      if(outputText != ""){
        var aTextNode = ce("div");
        aTextNode.innerHTML = outputText;
        aScript.parentNode.insertBefore(aTextNode, aScript.nextSibling);
      }
    }
  }

  // restore the old write functions
  document.write = oldWrite;
  document.writeln = oldWriteln;
}

function document_clicked(aEvent){
  return(
    ((aEvent.target != undefined) && (aEvent.target == document.body)) || // FF
    ((aEvent.srcElement != undefined) && (aEvent.srcElement == document.body))  // IE
  );
}

function clearSelection(){
  var sel;
  if(document.selection && document.selection.empty){
    document.selection.empty();
  }
  else if(window.getSelection){
    sel = window.getSelection();
    if(sel && sel.removeAllRanges){
      sel.removeAllRanges();
    }
  }
}

function cancel_selection(){
  clearSelection();
}

function stop_click(aEvent, aOnClick){
  if(!aEvent){aEvent = event;}

  if(document_clicked(aEvent)){
    // the document has been clicked
    aOnClick(aEvent);
  }

  if(aEvent.preventDefault){
    aEvent.preventDefault();
  }

  aEvent.returnValue = false;

  aEvent.cancelBubble = true;

  return(false);
}

/* Images */

function preload(aImageSrc, aOnLoad){
  // preload an image and optionally call aOnLoad when it is loaded
  var aNewImage = new Image;
  if(aOnLoad != undefined){
    aNewImage.onload = aOnLoad;
  }
  aNewImage.src = aImageSrc;
}

/* cookies */

function set_cookie(name, value, expires, path, domain, secure){
  document.cookie = name + "=" + escape(value) +
    ((expires) ? "; expires=" + expires.toGMTString() : "") +
    ((path) ? "; path=" + path : "") +
    ((domain) ? "; domain=" + domain : "") +
    ((secure) ? "; secure" : "");
}

function cookie_value(key){ // a fortune
	var keypos = document.cookie.indexOf(key);
	var result = "";
	if(keypos != -1){
		result = document.cookie.substr(keypos + key.length + 1, document.cookie.length);
		var endpos = result.indexOf(";");
		if(endpos != -1){
			result = result.substr(0, endpos);
		}
	}
	return (result);
}

/* maths */

function dec_to_hex(aDec){
  return(aDec.toString(16).toUpperCase());
}

function hex_to_dec(aHex){
  return(parseInt(aHex, 16));
}

function round_to_nearest(aValue, aRounding){
  return(Math.round(parseInt(aValue)/aRounding)*aRounding);
}

/* URL */

function random_query_string(){ // todo move
  // return a (pseudo) random string - use in a url query to avoid caching
  var aRandom = (new Date()).valueOf();
  return("RANDOM_STRING=" + aRandom);
}

function query_string(aQuery, aName){
  if(aName == undefined){
    // can leave out aQuery and then swap the params
    aName = aQuery;
    aQuery = document.location.search;
  }

  var aQPos = aQuery.search(/\?/);
  if(aQPos != -1){
    aQuery = aQuery.substr(aQPos+1);
  }

  var queryArray = aQuery.split("&");
  var result;

  for(var i=0; i<queryArray.length; i++){
    queryArray[i] = queryArray[i].split("=");
    if(queryArray[i][0] == aName){
      result = queryArray[i][1];
      break;
    }
  }
  return(result);
}

function qs(aQuery, aName){
  // shorthand for query_string
  return(query_string(aQuery, aName));
}

function add_query_string(aUrl, aQueryString){
  var result = aUrl;
  if(aUrl.search(/\?/) == -1){
    result += "?";
  }
  else{
    result += "&";
  }
  result += aQueryString;
  return(result);
}

function is_gtcms_page(aUrl){
  // return true if aUrl has a "page="
  return(aUrl.search(/page=/) != -1);
}

function gtcms_page_url(aUrl){
  var aName = qs(aUrl, "page");
  aName = aName.replace(/\ /g, "_");
  aName = aName.replace(/%20/g, "_");

  var aPathName = "http://" + extract_url(add_http(aUrl));
  var aUrl = aPathName + "/?page="+aName;
  return(aUrl);
}

function extract_url(aUrl){
  // return aUrl without path
  var aPos = aUrl.search(/\:\/\//);
  aUrl = aUrl.substr(aPos + 3);
  var aPos = aUrl.search(/\//);
  aUrl = aUrl.substr(0, aPos);

  return(aUrl);
}

function gtcms_edit_url(aUrl){
  var aName = qs(aUrl, "page");
  var aUrl = "";
  if(aName != undefined){
    aName = aName.replace(/\ /g, "_");
    aName = aName.replace(/%20/g, "_");

    var aPathName = "http://" + extract_url(add_http(aUrl));
    aUrl = aPathName + "/gtcms/edit_content.php?page="+aName;
  }
  return(aUrl);
}

/* Dimensions */

function scrollLeft(){
  return(document.documentElement.scrollLeft ?
     document.documentElement.scrollLeft :
     document.body.scrollLeft);
}

function scrollTop(){
  return(document.documentElement.scrollTop ?
     document.documentElement.scrollTop :
     document.body.scrollTop);
}

function isCSSFloat(aElement){
  var aFloat = getCSSAttribute(aElement, "float");
  if(aFloat != undefined){
    aFloat = trim(aFloat);
  }
  return((aFloat != undefined) && ((aFloat == "left") || (aFloat == "right")));
}

function absoluteLeftAnyFloatParent(aElement){
  var result = 0;
  if(aElement != undefined){
    var aParent = aElement.parentNode;
    if((aParent != undefined) && (aParent != document)){
      if(isCSSFloat(aParent)){
        result = absoluteLeft(aParent);
      }
      else{
        result = absoluteLeftAnyFloatParent(aParent);
      }
    }
  }
  return(result);
}


function absoluteLeft(aElement){
  // todo - make betterererera
  var result = 0;
  if(aElement != undefined){
    if((aElement != undefined) && (aElement != document.body)){
      result = aElement.offsetLeft - aElement.scrollLeft + absoluteLeft(aElement.offsetParent);
    }
  }
  return(result);
}

function absoluteTop(aElement){
  var result = 0;
  if((aElement != undefined) && (aElement != document.body)){
    if(aElement.offsetTop != undefined){
      result = aElement.offsetTop - aElement.scrollTop + absoluteTop(aElement.offsetParent);
    }
  }
  return(result);
}

function keep_in_parent(aElement){
  // move aElement so that top,left are within parent (x1,y1)-(x2,y2)
  var aParent = aElement.parentNode;

  assert(aParent != undefined);

  var aLeft = parseInt(aElement.offsetLeft);
  var aTop = parseInt(aElement.offsetTop);
  var aWidth = parseInt(aElement.offsetWidth);
  var aHeight = parseInt(aElement.offsetHeight);

  var aParentWidth = parseInt(aParent.offsetWidth);
  var aParentHeight = parseInt(aParent.offsetHeight);

  if(aLeft < 0){
    aElement.style.left = "0px";
  }
  else if((aLeft+aWidth) >= aParentWidth){
    setCSSAttribute(aElement, "left", aParentWidth - aWidth);
  }

  if(aTop < 0){
    aElement.style.top = "0px";
  }
  else if((aTop+aHeight) >= aParentHeight){
    setCSSAttribute(aElement, "top", aParentHeight - aHeight);
  }

}


function keep_on_screen(aElement){
  // todo - i dont think this works properly yet :)
  var MARGIN = 2;

  var aLeft = parseInt(aElement.style.left, 10);
  var aTop = parseInt(aElement.style.top, 10);

  var aWidth = parseInt(aElement.style.width, 10);
  if(aWidth == 0){
    aWidth = aElement.offsetWidth;
  }

  var aHeight = parseInt(aElement.style.height, 10);
  if(aHeight == 0){
    aHeight = aElement.clientHeight;
  }

  if(aLeft < scrollLeft()){
    set_left(aElement, scrollLeft());
  }

  if(aTop < scrollTop()){
    set_top(aElement, scrollTop());
  }

  if((aLeft + aWidth) > (scrollLeft() + document.body.clientWidth)){
    set_left(aElement, ((scrollLeft() + document.body.clientWidth) - aWidth - MARGIN));
  }

  if((aTop + aHeight) > (scrollTop() + document.body.clientHeight)){
    set_top(aElement, ((scrollTop() + document.body.clientHeight) - aHeight - MARGIN));
  }
}

function mouse_over_element(aEvent, aElement){
  var aLeft = absoluteLeft(aElement);
  var aTop = absoluteTop(aElement);
  var aWidth = aElement.offsetWidth;
  var aHeight = aElement.offsetHeight;
  var X = mouseX(aEvent);
  var Y = mouseY(aEvent);

  var result = (X >= aLeft) && (X < (aLeft+aWidth)) &&
    (Y >= aTop) && (Y < (aTop+aHeight));

  return(result);
}

/* original mouseX mouseY mouse functions from http://javascript.about.com/library/blmousepos.htm */

function mouseX(aEvent){
  if(!aEvent){aEvent = event;}

  if(aEvent.pageX){
    return(aEvent.pageX);
  }
  else if(aEvent.clientX){
    return aEvent.clientX + scrollLeft();
  }
  else{
    return(null);
  }
}

function mouseY(aEvent){
  if(!aEvent){aEvent = event;}

  if(aEvent.pageY){
    if(IS_FF && (aEvent.pageY<0)){
      return(0); // ff does weird things when an iframe is involved
    }
    else{
      return(aEvent.pageY);
    }
  }
  else if(aEvent.clientY){
    return(aEvent.clientY + scrollTop());
  }
  else{
    return(null);
  }
}

function mouse_button(aEvent){
  // return LEFT_MOUSE_BUTTON, MIDDLE_MOUSE_BUTTON, RIGHT_MOUSE_BUTTON
  var rightclick;
	if(!aEvent){aEvent = event;}
	if(aEvent.which){
    result = aEvent.which;
  }
	else if(aEvent.button){
    if(aEvent.button == 1){
      result = LEFT_MOUSE_BUTTON;
    }
    else if(aEvent.button == 4){
      result = MIDDLE_MOUSE_BUTTON;
    }
    else if(aEvent.button == 2){
      result = RIGHT_MOUSE_BUTTON;
    }
    else{
      result = UNKNOWN_MOUSE_BUTTON;
    }
  }
  else{
    result = UNKNOWN_MOUSE_BUTTON;
  }
  return(result);
}

function event_key(aEvent){
  var result;
	if(aEvent.which){
    result = aEvent.which;
  }
  else{
    result = aEvent.keyCode;
  }
  return(result);
}

function init_item_hover_info(aItem, aClassName, aNormalCSS, aHoverCSS){
  assert(getCSSClassInfo != undefined);

  if((aItem.menu_init_done == undefined) && (aNormalCSS != undefined) && (aHoverCSS != undefined)){
    aItem.menu_init_done = true;

    if(aClassName==undefined){
      aClassName = getAttributeText(aItem, "sub_class");
    }

    if(aNormalCSS == undefined){
      aNormalCSS = getCSSClassInfo("."+aClassName);
    }

    if(aHoverCSS == undefined){
      aHoverCSS = getCSSClassInfo("."+aClassName+":hover");
    }

    if((aItem.normalCSS == undefined) && (aHoverCSS != "")){
      aItem.normalCSS = aNormalCSS;
      aItem.hoverCSS = aHoverCSS;

      aItem.originalCSS = getAttributeText(aItem, "style");
      if(aItem.originalCSS == undefined){
        aItem.originalCSS = "";
      }

      aItem.doSetCSS = bind(aItem, function(aValue){
        if(IS_IE){
          this.style.cssText = aValue;
        }
        else{
          this.setAttribute("style", aValue);
        }
      });

      aItem.onmouseover = chain(aItem.onmouseover, bind(aItem, function(){
        this.doSetCSS(this.originalCSS + this.normalCSS + this.hoverCSS);
      }));

      aItem.onmouseout = chain(aItem.onmouseover, bind(aItem, function(){
        this.doSetCSS(this.originalCSS + this.normalCSS);
      }));
    }
  }
}

function init_hover_info(aClassName, aIncludeSubClass){

  var aNormalCSS = getCSSClassInfo("."+aClassName);
  var aHoverCSS = getCSSClassInfo("."+aClassName+":hover");

  if(aNormalCSS == undefined){
    aNormalCSS = "";
  }

  if(aHoverCSS == undefined){
    aHoverCSS = "";
  }

  var allHoverItems = get_all_class("div", aClassName, aIncludeSubClass);

  for(var i=0; i<allHoverItems.length; i++){
    var aItem = allHoverItems[i];
    init_item_hover_info(aItem, aClassName, aNormalCSS, aHoverCSS);
  }
}

function q_table(aRows, aCols){
  // quick dom table create

  var aTable = ce("table");
  var aTBODY = ce("tbody");
  aTBODY.table = aTable;
  aTable.tbody = aTBODY;
  aTable.appendChild(aTBODY);

  aTBODY.tr = new Array();

  for(iRow=0; iRow<aRows; iRow++){
    var aTR = ce("tr");
    aTR.tbody = aTBODY;
    aTBODY.tr[iRow] = aTR;
    aTBODY.appendChild(aTR);

    aTR.td = new Array();

    for(iCol=0; iCol<aCols; iCol++){
      var aTD = ce("td");
      aTD.tr = aTR;
      aTR.td[iCol] = aTD;
      aTR.appendChild(aTD);
    }
  }

  return(aTable);
}

function process_file_list(aPageText){
  var result = new Array();

  if(aPageText == undefined){
    result = undefined;
  }
  else{
    result += aPageText;

    result = result.split("\n");

    // remove unwanted entries
    result.pop(); // remove blank entry from end
    result.pop(); // remove ")" from end

    result.shift(); // remove "Array" from start
    result.shift(); // remove "(" from start

    for(var i=0; i<result.length; i++){
      result[i] = result[i].split("=>");

      result[i][0] = trim(result[i][0]);
      result[i][1] = trim(result[i][1]);

      // remove the []
      result[i][0] = result[i][0].substr(1, result[i][0].length-2);

      // only really need the filename - todo tidy up
      result[i] = result[i][1];
    }

    if((result.length > 0) && (result[0] == "./")){
      result.shift(); // remove .
    }
  }

  return(result);
}

function get_file_list(aDir, aFileListScriptUrl, aDocOnLoad, aMask){
  // return array of file names from given dir using the given script
  var result = new Array();

  if(aDir == undefined){
    aDir = "";
  }
  else{
    aDir = "?dir=" + aDir;
  }

  if(aMask == undefined){
    aMask = "";
  }
  else{
    aMask = "&mask=" + aMask;
  }

  if(aDocOnLoad == undefined){
    var aPageText = load_text(aFileListScriptUrl + encodeURI(aDir + aMask), aDocOnLoad, false);

    result = process_file_list(aPageText);
  }
  else{
    // asynch
    function do_process(aPageText){
      aDocOnLoad(process_file_list(aPageText));
    }
    result = load_text(aFileListScriptUrl + aDir + aMask, do_process, false);
  }

  return(result);
}

function extract_path(aFilename){
  assert(aFilename != undefined, "function extract_path(aFilename) aFilename cannot be undefined");
  var aLastSlashPos = 0;
  for(var i=0; i<aFilename.length; i++){
    if(aFilename.substr(i, 1) == "/"){
      aLastSlashPos = i + 1;
    }
  }
  return(aFilename.substr(0, aLastSlashPos));
}

function extract_filename(aFilename){
  assert(aFilename != undefined, "aFilename != undefined");
  var aLastSlashPos = 0;
  for(var i=0; i<aFilename.length; i++){
    if(aFilename.substr(i, 1) == "/"){
      aLastSlashPos = i + 1;
    }
  }
  return(aFilename.substr(aLastSlashPos));
}

function extract_fileext(aFilename){
  assert(aFilename != undefined, "aFilename != undefined");
  var aLastDotPos = aFilename.length;
  for(var i=0; i<aFilename.length; i++){
    if(aFilename.substr(i, 1) == "."){
      aLastDotPos = i + 1;
    }
  }
  return(aFilename.substr(aLastDotPos));
}

function remove_file_ext(aFilename){
  var aFileExt = extract_fileext(aFilename);
  if(aFileExt!=""){
    aFilename = aFilename.substr(0, (aFilename.length - aFileExt.length - 1));
  }
  return(aFilename);
}

function ensure_file_ext(aFilename, aFileExt){
  if(!tail_is(aFilename, aFileExt)){
    aFilename += aFileExt;
  }
  return(aFilename);
}

function is_image_file(aFilename){
  return(in_array(extract_fileext(aFilename), IMAGE_FILES));
}

function remove_head_slash(aString){
  if( head_is(aString, "/") || head_is(aString, "\\") ){
    aString = aString.substr(1);
  }
  return(aString);
}

function end_slash(aString){
  if(aString.substr(aString.length-1, 1) != "/"){
    aString += "/";
  }
  return(aString);
}

function add_path(aPath, aNewPath){
  // add aNewPath to aPath or go up one directory if aNewPath is ../
  var result = aPath;
  if(aNewPath == "/"){
    result = "/";
  }
  else if((aNewPath == "../") || (aNewPath == "..")){
    var aFolders = result.split("/");
    aFolders.pop();
    aFolders.pop();
    result = aFolders.join("/");
  }
  else{
    result = end_slash(result) + aNewPath;
  }
  return(result);
}

function create_range(selectionObject){
  var result;
	if (selectionObject.getRangeAt != undefined){
		result = selectionObject.getRangeAt(0);
	}
	else if(selectionObject.createRange != undefined){
    result = selectionObject.createRange();
  }
	else if(document.createRange != undefined){
		result = document.createRange();
		result.setStart(selectionObject.anchorNode, selectionObject.anchorOffset);
		result.setEnd(selectionObject.focusNode, selectionObject.focusOffset);
	}
	return(result);
}

function get_selection(aWindow){
  if(aWindow == undefined){
    aWindow = window;
  }

  var result;
  var aDoc = aWindow.document;

  if(aWindow.getSelection){
  	result = aWindow.getSelection();
  }
  else if(aDoc.selection){
  	result = aDoc.selection;
  	if(result != undefined){
      result.toString = bind(result, function(){
        var result = "";
        var aRange = create_range(this);

        if(aRange != undefined){
          result = aRange.text;
        }
        return(result);
      });
    }
 	}
  return(result);
}

function geid(aId){
  // shorthand for document.getElementById
  return(document.getElementById(aId));
}

function ce(aTagName){
  // shorthand for document.createElement
  return(document.createElement(aTagName));
}

function getn(aTagName){
  // shorthand for document.getElementsByTagName
  return(document.getElementsByTagName(aTagName));
}

function check_select_template(){
  if((qs("select_template") == "true") && (select_template != undefined)){
    select_template();
  }
}
