/* 
 * Copyright 2009 MightyCloud, Inc. All rights reserved.
 * MIGHTYCLOUD PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */

function $() {
    var elements = new Array();
    for (var i = 0; i < arguments.length; i++) {
        var element = arguments[i];
        if (typeof element == 'string')
            element = document.getElementById(element);
        if (arguments.length == 1)
            return element;
        elements.push(element);
    }
    return elements;
}


/**
 * make(tagname, attributes, children):
 *   create an HTML element with specified tagname, attributes and children.
 *
 * The attributes argument is a JavaScript object: the names and values of its
 * properties are taken as the names and values of the attributes to set.
 * If attributes is null, and children is an array or a string, the attributes
 * can be omitted altogether and the children passed as the second argument.
 *
 * The children argument is normally an array of children to be added to
 * the created element.  If there are no children, this argument can be
 * omitted.  If there is only a single child, it can be passed directly
 * instead of being enclosed in an array. (But if the child is not a string
 * and no attributes are specified, an array must be used.)
 *
 * Example: make("p", ["This is a ", make("b", "bold"), " word."]);
 *
 * Inspired by the MochiKit library (http://mochikit.com) by Bob Ippolito
 */
function make(tagname, attributes, children) {

    // If we were invoked with two arguments the attributes argument is
    // an array or string, it should really be the children arguments.
    if (arguments.length == 2 &&
        (attributes instanceof Array || typeof attributes == "string")) {
        children = attributes;
        attributes = null;
    }

    // Create the element
    var e = document.createElement(tagname);

    // Set attributes
    if (attributes) {
        for(var name in attributes) e.setAttribute(name, attributes[name]);
    }

    // Add children, if any were specified.
    if (children != null) {
        if (children instanceof Array) {  // If it really is an array
            for(var i = 0; i < children.length; i++) { // Loop through kids
                var child = children[i];
                if (typeof child == "string")          // Handle text nodes
                    child = document.createTextNode(child);
                e.appendChild(child);  // Assume anything else is a Node
            }
        }
        else if (typeof children == "string") // Handle single text child
            e.appendChild(document.createTextNode(children));
        else e.appendChild(children);         // Handle any other single child
    }

    // Finally, return the element.
    return e;
}

/**
 * maker(tagname): return a function that calls make() for the specified tag.
 * Example: var table = maker("table"), tr = maker("tr"), td = maker("td");
 */
function maker(tag) {
    return function(attrs, kids) {
        if (arguments.length == 1) return make(tag, attrs);
        else return make(tag, attrs, kids);
    }
}

function firstChild(elem, type)
{
    var child = elem.firstChild;
    while (child)
    {
        if (child.nodeType == type)
            return child;
        child = child.nextSibling; 
    }
    return null; 
}

function getElementsByAttribute(oElm, strTagName, strAttributeName, strAttributeValue) {
    var arrElements = (strTagName == "*" && oElm.all)? oElm.all : oElm.getElementsByTagName(strTagName);
    var arrReturnElements = new Array();
    var oAttributeValue = (typeof strAttributeValue != "undefined")? new RegExp("(^|\\s)" + strAttributeValue + "(\\s|$)") : null;
    var oCurrent;
    var oAttribute;
    for(var i=0; i<arrElements.length; i++){
        oCurrent = arrElements[i];
        oAttribute = oCurrent.getAttribute && oCurrent.getAttribute(strAttributeName);
        if(typeof oAttribute == "string" && oAttribute.length > 0){
            if(typeof strAttributeValue == "undefined" || (oAttributeValue && oAttributeValue.test(oAttribute))){
                arrReturnElements.push(oCurrent);
            }
        }
    }
    return arrReturnElements;
}

function strtrim() {
    return this.replace(/^\s+/,'').replace(/\s+$/,'');
}
String.prototype.trim = strtrim;

function truncate(maxlen) {
    if (this.trlength <= maxlen)
        return this
    else if (maxlen < 4)
        return this.substring(0, maxlen) // no room for ellipsis
    else
        return this.substring(0, maxlen-3) + "...";
}
String.prototype.truncate = truncate; 

function isNull(what) {
    return what==null
}

function isArray(obj) {
    return obj.constructor == Array;
}

function toggle(openid, closeid) {
    var openElem = document.getElementById(openid);
    var closeElem = document.getElementById(closeid);
    closeElem.style.display = 'none';
    openElem.style.display = '';
    return false;
}

// sets the value of a span field
function setField(elem, fieldName, fieldValue)
{
    var fieldElem = getElementsByAttribute(elem, 'span', 'id', fieldName)[0];
    if (!isNull(fieldElem)) fieldElem.innerHTML = fieldValue;
}

// gets the value of a span field 
function getField(elem, fieldName)
{
    var fieldElem = getElementsByAttribute(elem, 'span', 'id', fieldName)[0];
    return (isNull(fieldElem)) ? null : fieldElem.innerHTML;
}

/**
 * Methods for managing cookies 
 */
function createCookie(name,value,days) {
    if (days) {
        var date = new Date();
        date.setTime(date.getTime()+(days*24*60*60*1000));
        var expires = "; expires="+date.toGMTString();
    }
    else expires = "";
    document.cookie = name+"="+value+expires+"; path=/";
}

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

function eraseCookie(name) {
    createCookie(name,"",-1);
}

/**
 * Invoke REST methods
 */
function doGet(url, callback, failureCallback)
{
    // create the request object
    var xmlhttp = null;
    if (window.XMLHttpRequest) {
        xmlhttp = new XMLHttpRequest();
        if ( typeof xmlhttp.overrideMimeType != 'undefined') {
            xmlhttp.overrideMimeType('text/xml');
        }
    } else if (window.ActiveXObject) {
        xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
    } else {
        alert('Perhaps your browser does not support xmlhttprequests?');
    }

    // invoke the rest method
    xmlhttp.open('GET', url, true);
    xmlhttp.send(null);

    // process the result asyncronously 
    xmlhttp.onreadystatechange = function() {
        if (xmlhttp.readyState == 4) {
            if (xmlhttp.status == 200) {
                var responseObj = eval("(" + xmlhttp.responseText + ")");
                callback(responseObj);
            } else if(failureCallback) {
                failureCallback("Could not communicate with the server.");
            }
        } 
    };
}

// enforces the text length limit in an input field 
function limitText(limitField, limitCount, limitNum)
{
    if (limitField.value.length > limitNum) {
        limitField.value = limitField.value.substring(0, limitNum);
    } else {
        limitCount.innerHTML = limitNum - limitField.value.length;
    }
}

function isValidEmail(email)
{
    email = email.trim();
    var reEmail = new RegExp('^[0-9a-zA-Z]{1}[0-9a-zA-Z\.+-_]*@[0-9a-zA-Z\-]+[\.]{1}[0-9a-zA-Z]+[\.]?[0-9a-zA-Z]+$');
    return reEmail.exec(email) ? true : false;
}

function isValidPhone(phone)
{
    var stripped = phone.replace(/[\(\)\.\-\ ]/g, '');
    return (stripped != "" && !isNaN(parseInt(stripped)) && (stripped.length == 10 || stripped.length == 11 && stripped.charAt(0) == '1'));
}

function isAllowedFileType(value)
{
    var supportedTypes = MM.Configuration.getSupportedTypes();
    if(!supportedTypes)
    {
        window.alert("Warning, supportedTypes is not set");
        return false;
    }
    
    value = value.trim();
    value = value.toLowerCase();
    supportedTypes = supportedTypes.split(",");
    var reFileExtension = /^.*\.(\w+)$/;
    var res = value.match(reFileExtension);
    
    return (res && (indexOf(supportedTypes, res[1]) != -1));
}

function indexOf(arr, obj, start)
{
    for (var i = (start || 0); i < arr.length; i++) 
    {
        if (arr[i] == obj) 
        {
          return i;
        }
    }
    
    return -1;
}

Date.prototype.setISO8601 = function(dString)
{
    var regexp = /(\d\d\d\d)(-)?(\d\d)(-)?(\d\d)(T)?(\d\d)(:)?(\d\d)(:)?(\d\d)(\.\d+)?(Z|([+-])(\d\d)(:)?(\d\d))/;

    if (dString.toString().match(new RegExp(regexp))) {
        var d = dString.match(new RegExp(regexp));
        var offset = 0;

        this.setUTCDate(1);
        this.setUTCFullYear(parseInt(d[1],10));
        this.setUTCMonth(parseInt(d[3],10) - 1);
        this.setUTCDate(parseInt(d[5],10));
        this.setUTCHours(parseInt(d[7],10));
        this.setUTCMinutes(parseInt(d[9],10));
        this.setUTCSeconds(parseInt(d[11],10));
        if (d[12])
            this.setUTCMilliseconds(parseFloat(d[12]) * 1000);
        else
            this.setUTCMilliseconds(0);
        if (d[13] != 'Z') {
            offset = (d[15] * 60) + parseInt(d[17],10);
            offset *= ((d[14] == '-') ? -1 : 1);
            this.setTime(this.getTime() - offset * 60 * 1000);
        }
    }
    else {
        this.setTime(Date.parse(dString));
    }
    return this;
}

Date.prototype.toISO8601String = function (format, offset) {
    /* accepted values for the format [1-6]:
     1 Year:
       YYYY (eg 1997)
     2 Year and month:
       YYYY-MM (eg 1997-07)
     3 Complete date:
       YYYY-MM-DD (eg 1997-07-16)
     4 Complete date plus hours and minutes:
       YYYY-MM-DDThh:mmTZD (eg 1997-07-16T19:20+01:00)
     5 Complete date plus hours, minutes and seconds:
       YYYY-MM-DDThh:mm:ssTZD (eg 1997-07-16T19:20:30+01:00)
     6 Complete date plus hours, minutes, seconds and a decimal
       fraction of a second
       YYYY-MM-DDThh:mm:ss.sTZD (eg 1997-07-16T19:20:30.45+01:00)
    */
    if (!format) {var format = 6;}
    if (!offset) {
        var offset = 'Z';
        var date = this;
    } else {
        var d = offset.match(/([-+])([0-9]{2}):([0-9]{2})/);
        var offsetnum = (Number(d[2]) * 60) + Number(d[3]);
        offsetnum *= ((d[1] == '-') ? -1 : 1);
        var date = new Date(Number(Number(this) + (offsetnum * 60000)));
    }

    var zeropad = function (num) {return ((num < 10) ? '0' : '') + num;}

    var str = "";
    str += date.getUTCFullYear();
    if (format > 1) {str += "-" + zeropad(date.getUTCMonth() + 1);}
    if (format > 2) {str += "-" + zeropad(date.getUTCDate());}
    if (format > 3) {
        str += "T" + zeropad(date.getUTCHours()) +
               ":" + zeropad(date.getUTCMinutes());
    }
    if (format > 5) {
        var secs = Number(date.getUTCSeconds() + "." +
                   ((date.getUTCMilliseconds() < 100) ? '0' : '') +
                   zeropad(date.getUTCMilliseconds()));
        str += ":" + zeropad(secs);
    } else if (format > 4) {str += ":" + zeropad(date.getUTCSeconds());}

    if (format > 3) {str += offset;}
    return str;
}

Date.prototype.isToday = function ()
{
    var now = new Date();
    return this.getYear() == now.getYear() &&
        this.getDate() == now.getDate() &&
        this.getMonth() == now.getMonth(); 
}

Date.prototype.timezone = function()
{
    var timezonePattern = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g;
    var timezoneClip = /[^-+\dA-Z]/g;
    return (String(this).match(timezonePattern) || [""]).pop().replace(timezoneClip, "");
}

Date.prototype.getTZOffset = function()
{
    var dtDate = new Date('1/1/' + (new Date()).getUTCFullYear());
    var intOffset = 10000; 
    var intMonth;
    for (intMonth=0;intMonth < 12;intMonth++)
    {
        dtDate.setUTCMonth(dtDate.getUTCMonth() + 1);
        if (intOffset > (dtDate.getTimezoneOffset() * (-1)))
        {
            intOffset = (dtDate.getTimezoneOffset() * (-1));
        }
    }
    return intOffset;
}

/**
* Create and return a "version 4" RFC-4122 UUID string.
*/
function randomUUID()
{
    var s = [], itoh = '0123456789ABCDEF';

    // Make array of random hex digits. The UUID only has 32 digits in it, but we
    // allocate an extra items to make room for the '-'s we'll be inserting.
    for (var i = 0; i <36; i++) s[i] = Math.floor(Math.random()*0x10);

    // Conform to RFC-4122, section 4.4
    s[14] = 4;  // Set 4 high bits of time_high field to version
    s[19] = (s[19] & 0x3) | 0x8;  // Specify 2 high bits of clock sequence

    // Convert to hex chars
    for (i = 0; i <36; i++) s[i] = itoh[s[i]];

    // Insert '-'s
    s[8] = s[13] = s[18] = s[23] = '-';

    return s.join('');
}

function initInput(input)
{
    input.onfocus = function(e)
    {
        if(input.value.trim() == input.defaultValue) input.value = "";
    }
    input.onblur = function(e)
    {
        if(input.value.trim() == "")
        {
            input.value = input.defaultValue;
        }
    }
}

