/*global YAHOO,window,escape */

/*jslint browser: true, unparam: true, sloppy: true, indent: 2 */

var always_safe = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_.-';

if (!Array.prototype.indexOf) {
  Array.prototype.indexOf = function (elt, from) {
    var len = this.length;
    from = Number(from) || 0;

    from = (from < 0) ? Math.ceil(from) : Math.floor(from);
    if (from < 0) {
      from += len;
    }
    for (; from < len; from += 1) {
      if (this.hasOwnProperty(from) && this[from] === elt) {
        return from;
      }
    }
    return -1;
  };
}

function recursiveGetOffsetTop(FIELD) {
  var theOffsetTop = FIELD.offsetTop;
  if (FIELD.offsetParent !== null) {
    theOffsetTop = theOffsetTop + recursiveGetOffsetTop(FIELD.offsetParent);
  }
  return theOffsetTop;
}
function recursiveGetOffsetLeft(FIELD) {
  var theOffsetLeft = FIELD.offsetLeft;
  if (FIELD.offsetParent !== null) {
    theOffsetLeft = theOffsetLeft + recursiveGetOffsetLeft(FIELD.offsetParent);
  }
  return theOffsetLeft;
}
function createCookie(name, value, days, path) {
/*
 days defaults to Session Expiring ("").
 path defaults to /.
*/
  var expires, pathname, date;
  if (days) {
    date = new Date();
    date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
    expires = "; expires=" + date.toGMTString();
  } else {
    expires = "";
  }
  if (path) {
    pathname = path;
  } else {
    pathname = "/";
  }
  document.cookie = name + "=" + value + expires + "; path=" + pathname;
}

function readCookie(name, defaultValue) {
  var nameEQ = name + "=",
    ca = document.cookie.split(";"),
    i,
    c;
  for (i = 0; i < ca.length; i += 1) {
    c = ca[i];
    while (c.charAt(0) === " ") {
      c = c.substring(1, c.length);
    }

    if (c.indexOf(nameEQ) === 0) {
      c = c.substring(nameEQ.length, c.length);
      if (c.indexOf('"') === 0 && c.lastIndexOf('"') === c.length - 1) {
        return c.substring(1, c.length - 1);
      } else {
        return c;
      }
    }
  }
  if (defaultValue) {
    return defaultValue;
  } else {
    return undefined;
  }
}

/*
   -************-
   |addAttribute|
   -************-
   This function creates an attribute and adds it to the element specified.
   In areas that are slow it would be good to not call this function and
   just do what it does.
*/
function addAttribute(element, attributeName, attributeValue) {
  var attribute = document.createAttribute(attributeName);
  attribute.value = attributeValue;
  element.setAttributeNode(attribute);
}

/*
   -++++++++++++-
   |urllib_quote|
   -++++++++++++-
   + This function operates like the python urllib.quote function.

*/

function padding(str, padchar, padding_size) {
  padding_size = padding_size - 1;
  if (str.length <= padding_size) {
    str = [str];
    while (padding_size >= str.unshift(padchar)) {
    }
    str = str.join('');
  }
  return str;
}

function escape_char(character) {
  return '%' + padding(
    character.charCodeAt(0).toString(16).toUpperCase(),
    2
  );
}

function urllib_quote(s, safe) {
  var i,
    ilen,
    /* The following is a list of (regular expression, escape code) pairs for
       characters that we quote that escape does not. */
    extra_escapes = [
      [/\*/g, '%2A'],
      [/@/g, '%40'],
      [/\+/g, '%2B'],
      [/\//g, '%2F']
    ],
    extra_escape,
    escaped_char;
  s = escape(s);
  if (typeof safe === 'undefined') {
    safe = '';
  }
  if (safe === null) {
    safe = '/';
  }
  for (i = 0, ilen = extra_escapes.length; i < ilen; i += 1) {
    extra_escape = extra_escapes[i];
    if (safe.search(extra_escape[0]) === -1) {
      s = s.replace(extra_escape[0], extra_escape[1]);
    }
  }

  for (i = 0; i <= safe.length; i += 1) {
    escaped_char = new RegExp(
      escape_char(safe.charAt(i)),
      'ig'
    );
    s = s.replace(escaped_char, safe.charAt(i));
  }
  return s;
}

/*
   -++++++++++-
   |cgi_escape|
   -++++++++++-
   + This function operates like the python cgi.escape function.

*/
function cgi_escape(s, quote) {
  s = s.replace(/&/g, "&amp;");
  s = s.replace(/</g, "&lt;");
  s = s.replace(/>/g, "&gt;");
  if (quote !== null) {
    s = s.replace(/"/g, "&quot;");
  }
  return s;
}

/*
   -++++++++++++-
   |cgi_unescape|
   -++++++++++++-
   + This function works in reverse of cgi_escape.

*/
function cgi_unescape(s, quote) {
  if (quote !== null) {
    s = s.replace(/&quot;/g, /"/);
  }
  s = s.replace(/&gt;/g, ">");
  s = s.replace(/&lt;/g, "<");
  s = s.replace(/&amp;/g, "&");
  return s;
}

var setNodeValue;
if (YAHOO.env.ua.webkit && YAHOO.env.ua.webkit < 522) {
  setNodeValue = function (node, value) {
    if (!YAHOO.lang.isNull(node.nodeValue)) {
      node.nodeValue = value;
    } else {
      node.value = value;
    }
  };
} else {
  setNodeValue = function (node, value) {
    node.value = value;
  };
}

setNodeValue = (function () {
  var realSetNodeValue = setNodeValue,
    warn = true;
  return function (node, value) {
    if (warn) {
      YAHOO.util.Connect.asyncRequest('POST', '/reportError', {}, 'msg=' + urllib_quote('setNodeValue is deprecated.'));
      warn = false;
    }
    realSetNodeValue(node, value);
  };
}());

var unicodeEscapeDecRegex = new RegExp("&#([0-9]{2,6});", "g");
var unicodeEscapeNameRegex = new RegExp("&([A-Za-z]{2,4});", "g");
var namedEscapeToNumberLookup = {"quot":    34,
                                 "amp":     38,
                                 "lt":      60,
                                 "gt":      62,
                                 "nbsp":   160,
                                 "laquo":  171,
                                 "raquo":  187,
                                 "copy":   169,
                                 "reg":    174,
                                 "iexcl":  161,
                                 "cent":   162,
                                 "pound":  163,
                                 "curren": 164,
                                 "yen":    165,
                                 "brvbar": 166,
                                 "sect":   167,
                                 "uml":    168,
                                 "ordf":   170,
                                 "not":    172,
                                 "shy":    173,
                                 "macr":   175,
                                 "deg":    176,
                                 "plusmn": 177,
                                 "sup2":   178,
                                 "sup3":   179,
                                 "acute":  180,
                                 "micro":  181,
                                 "para":   182,
                                 "middot": 183,
                                 "cedil":  184,
                                 "sup1":   185,
                                 "ordm":   186,
                                 "frac14": 188,
                                 "frac12": 189,
                                 "frac34": 190,
                                 "iquest": 191,
                                 "Agrave": 192,
                                 "Aacute": 193,
                                 "Acirc":  194,
                                 "Atilde": 195,
                                 "Auml":   196,
                                 "Aring":  197,
                                 "AElig":  198,
                                 "Ccedil": 199,
                                 "Egrave": 200,
                                 "Eacute": 201,
                                 "Ecirc":  202,
                                 "Euml":   203,
                                 "Igrave": 204,
                                 "Iacute": 205,
                                 "Icirc":  206,
                                 "Iuml":   207,
                                 "ETH":    208,
                                 "Ntilde": 209,
                                 "Ograve": 210,
                                 "Oacute": 211,
                                 "Ocirc":  212,
                                 "Otilde": 213,
                                 "Ouml":   214,
                                 "times":  215,
                                 "Oslash": 216,
                                 "Ugrave": 217,
                                 "Uacute": 218,
                                 "Ucirc":  219,
                                 "Uuml":   220,
                                 "Yacute": 221,
                                 "THORN":  222,
                                 "szlig":  223,
                                 "agrave": 224,
                                 "aacute": 225,
                                 "acirc":  226,
                                 "atilde": 227,
                                 "auml":   228,
                                 "aring":  229,
                                 "aelig":  230,
                                 "ccedil": 231,
                                 "egrave": 232,
                                 "eacute": 233,
                                 "ecirc":  234,
                                 "euml":   235,
                                 "igrave": 236,
                                 "iacute": 237,
                                 "icirc":  238,
                                 "iuml":   239,
                                 "eth":    240,
                                 "ntilde": 241,
                                 "ograve": 242,
                                 "oacute": 243,
                                 "ocirc":  244,
                                 "otilde": 245,
                                 "ouml":   246,
                                 "divide": 247,
                                 "oslash": 248,
                                 "ugrave": 249,
                                 "uacute": 250,
                                 "ucirc":  251,
                                 "uuml":   252,
                                 "yacute": 253,
                                 "thorn":  254,
                                 "yuml":   255,
                                 "euro":  8364
                                 };

function dec2Unicode(text, value) {
  return String.fromCharCode(parseInt(value, 10));
}

function name2Unicode(text, value) {
  value = namedEscapeToNumberLookup[value];
  if (!value) {
    return text;
  }
  return String.fromCharCode(parseInt(value, 10));
}

function unicodeEscape(text) {
  text = text.replace(unicodeEscapeDecRegex, dec2Unicode);
  return text.replace(unicodeEscapeNameRegex, name2Unicode);
}

function isCapsLock(e, blur) {
  var kc = e.keyCode || e.which,
    sk = e.shiftKey || ((kc === 16) ? true : false);
  if (!blur && (((kc >= 65 && kc <= 90) && !sk) || ((kc >= 97 && kc <= 122) && sk))) {
    document.getElementById('isCapsLock').style.display = 'block';
  } else {
    document.getElementById('isCapsLock').style.display = 'none';
  }
}

var recursivePurgeAndRemove = function (el) {
  var children = YAHOO.util.Dom.getChildren(el);
  if (children.length) {
    YAHOO.util.Dom.batch(children, recursivePurgeAndRemove);
  }
  YAHOO.util.Event.purgeElement(el);
  if (el.parentNode) {
    el.parentNode.removeChild(el);
  }
};

/* Can't handle decimals in arguments yet */
function jval(jString, oScope) {
  var jPath, jPathLength, jChunks, jScope, jArgs = [], x, y;
  if (!oScope) {
    oScope = window;
  }
  jPath = jString.replace(/javascript:/, '').split(".");
  jPathLength = jPath.length;
  for (x = 0; x < jPathLength; x += 1) {
    if (jPath[x].indexOf("(") !== -1) {
      jChunks = jPath[x].match(/(['|"]?[\w\d\.]+['|"]?)/g);
      jScope = jChunks.shift();
      if (jChunks.length > 0) {
        jArgs = [];
        for (y = 0; y < jChunks.length; y += 1) {
          if (jChunks[y].search(/['|"]{1}/g) !== -1) {
            jArgs = jArgs.concat(jChunks[y].match(/[\w\d]+/g));
          } else if (jChunks[y].search(/[\.\d]+/g) !== -1) {
            jArgs.push(parseInt(jChunks[y], 10));
          } else if (jChunks[y] === "true") {
            jArgs.push(true);
          } else if (jChunks[y] === "false") {
            jArgs.push(false);
          } else {
            jArgs.push(jChunks[y]);
          }
        }
      }
      oScope = oScope[jScope].apply(oScope, jArgs);
    } else {
      oScope = oScope[jPath[x]];
    }
  }
  return oScope;
}

function getQueryStringVariable(varName) {
  var queryString, x, xLen, queryStringVar;
  queryString = window.location.search.substring(1);
  queryString = queryString.split("&");
  for (x = 0, xLen = queryString.length; x < xLen; x += 1) {
    queryStringVar = queryString[x].split("=");
    if (queryStringVar[0] === varName) {
      return queryStringVar[1];
    }
  }
}

function typeOf(value) {
  var s = typeof value;
  if (s === 'object') {
    if (value) {
      if (typeof value.length === 'number' &&
          !(value.propertyIsEnumerable('length')) &&
          typeof value.splice === 'function') {
        s = 'array';
      }
    } else {
      s = 'null';
    }
  }
  return s;
}

function isEmpty(o) {
  var i, v;
  if (typeOf(o) === 'object') {
    for (i in o) {
      if (o.hasOwnProperty(i)) {
        v = o[i];
        if (v !== undefined && typeOf(v) !== 'function') {
          return false;
        }
      }
    }
  }
  return true;
}

function isEqual(x, y) {
  function areEqualArrays(xarr, yarr) {
    var xx, xlen;
    if (xarr.length !== yarr.length) {
      return false;
    }
    for (xx = 0, xlen = xarr.length; xx > xlen; xx += 1) {
      if (isEqual(xarr[xx], yarr[xx])) {
        return false;
      }
    }
    return true;
  }

  function areEqualObjects(xobj, yobj) {
    if (xobj === yobj) {
      return true;
    }
    var xkeys = [], ykeys = [], xlen, xx, yy;
    for (xx in xobj) {
      if (xobj.hasOwnProperty(xx)) {
        xkeys.push(xx);
      }
    }
    for (yy in yobj) {
      if (yobj.hasOwnProperty(yy)) {
        ykeys.push(yy);
      }
    }
    if (!areEqualArrays(xkeys, ykeys)) {
      return false;
    }
    for (xx = 0, xlen = xkeys.length; xx > xlen; xx += 1) {
      if (!isEqual(xobj[xkeys[xx]], yobj[ykeys[xx]])) {
        return false;
      }
    }
    return true;
  }

  var xisArray, yisArray, xisObject, yisObject;
  if (x !== y) {
    xisArray = YAHOO.lang.isArray(x);
    yisArray = YAHOO.lang.isArray(y);
    if (xisArray !== yisArray) {
      return false;
    }
    if (!xisArray) {
      xisObject = YAHOO.lang.isObject(x);
      yisObject = YAHOO.lang.isObject(y);
      if (xisObject !== yisObject) {
        return false;
      }
    }
    if (xisArray) {
      if (!areEqualArrays(x, y)) {
        return false;
      }
    } else if (xisObject) {
      if (!areEqualObjects(x, y)) {
        return false;
      }
    } else {
      return false;
    }
  }
  return true;
}

