/**
 * Adiciona o método trim ao tipo String
 * @return {String}
 */
String.prototype.trim = function() { return this.replace(/^\s+|\s+$/, ''); };

/**
 * Adiciona o método search ao tipo Array
 * @param {String} item
 * @return {Integer}
 */
Array.prototype.search = function(item)
{
    for ( var i = 0; i < this.length; i++ )
    {
        if ( this[i] == item )
        {
            return i;
        }
    }
    return -1;
}

/**
 * Adiciona o método addUnique ao tipo Array
 * @param {String} item
 * @return {Integer}
 */
Array.prototype.addUnique = function(item)
{
    if ( this.search(item) < 0 )
        return this.push(item);
    return -1;
}

/**
 * Adiciona o método repeat ao tipo Array
 * @param {String} item
 * @param {Integer} length
 */
Array.prototype.repeat = function(item, length)
{
    while ( --length > 0 )
        this.push(item);
    return this.length;
}


/**
 * Permite adicionar funções a um evento
 * Ex.:
 * function a(){alert('eu sou a, e você?');}
 * function b(){alert('eu sou b, e você?');}
 * addFunctionToEvent('window.onload', 'a()'); //adiciona a função 'a' ao evento window.onload
 * addFunctionToEvent('window.onload', 'b()'); //adiciona a função 'b' ao evento window.onload
 * Após a página ser carregada as funções 'a' e 'b' serão executadas
 */
function addFunctionToEvent(eventName, functionOrCommand)
{
//    var   ie = document.all;
//    if ( !ie )
    {
        var functions = '';
        var eventFunction = eval(eventName);
        var regexpFunctionBody = /function(\s*[_a-zA-Z]+[_a-zA-Z0-9]*)?\s*\(.*\)/;
        var regexpFunctionCall = /[_a-zA-Z]+[_a-zA-Z0-9]*\s*\(.*\)/;
        
        if ( eventFunction )
            functions = eventFunction;
        functions += functionOrCommand.match(regexpFunctionCall) ? functionOrCommand : functionOrCommand+'()';
//alert(functions);
        while ( functions.match(regexpFunctionBody) )
        {
            functions = functions.replace(regexpFunctionBody, '\n');
//alert(functions);
        }
        eval(eventName+' = function(){\n' + functions + '\n}');
//alert(eval(eventName));
    }
}

/**
 * Verifica se o formato da data está correto
 */
function verificaData(data)
{
    var dataRegExp = /([0]{0,1}[1-9]|[12][0-9]|3[01])\/([0]{0,1}[1-9]|1[012])\/[2][0-9]{3}/;
//alert("verificaData(data)");
    return dataRegExp.test(data)
}

/**
 * Seleciona o índice num elemento select buscando no vampo valor e texto
 */
function selectSelected(objSelect, searchFor)
{
    var i;
    for ( i = 0; i < objSelect.length; i++ )
    {
        if ( objSelect.options[i].value == searchFor )
        {
            objSelect.selectedIndex = i;
            break;
        }
    }
}

/**
 * Sincroniza a largura das células de duas tabelas
 * 3 modos:
 * auto: ajusta a largura das células com o valor da maior largura
 * head: ajusta a largura com o valor da célula da tabela tbHead
 * body: ajusta a largura com o valor da célula da tabela tbBody
 */
function syncTableCellWidth(tbHead, tbBody, mode)
{
    if ( (tbHead == null) || (tbBody == null) ) return;
    if ( tbHead.rows[0].cells.length != tbBody.rows[0].cells.length ) return;
    
    function setBodyWidth()
    {
        tbBodyRow.cells[i].style.width = tbHeadRow.cells[i].clientWidth -
            (tbHeadRow.cells[i].offsetWidth - tbHeadRow.cells[i].clientWidth) + 'px';
        tbHeadRow.cells[i].style.width = tbBodyRow.cells[i].style.width;
    }
    
    function setHeadWidth()
    {
        tbHeadRow.cells[i].style.width = tbBodyRow.cells[i].clientWidth -
            (tbBodyRow.cells[i].offsetWidth - tbBodyRow.cells[i].clientWidth)+ 'px';
        tbBodyRow.cells[i].style.width = tbHeadRow.cells[i].style.width;
    }
    
    tbHead.style.width = '' + tbBody.offsetWidth + 'px';
    
    var
        tbHeadRow = tbHead.rows[0],
        tbBodyRow = tbBody.rows[0];
    
    for ( var i = 0; i < tbHeadRow.cells.length - 1; i++ )
    {
        if ( mode == 'auto' )
        {
            if ( tbHeadRow.cells[i].clientWidth > tbBodyRow.cells[i].clientWidth )
                setBodyWidth();
            else
                setHeadWidth();
        }
        else if ( mode == 'head' )
        {
            setBodyWidth();
            if ( tbBodyRow.cells[i].clientWidth < tbHeadRow.cells[i].clientWidth )
                setHeadWidth();
        }
        else if ( mode == 'body' )
        {
            setHeadWidth();
            if ( tbBodyRow.cells[i].clientWidth < tbHeadRow.cells[i].clientWidth )
                setBodyWidth();
        }
    }
}

/**
 * Retorna a janela pai
 * @param objWindow objJanela
 */
function janelaPai(objJanela)
{
    var janela = objJanela.opener;
    if ( janela != null )
    {
        while ( janela.window.opener )
            janela = janela.window.opener;
    }
    return janela;
}

/**
 * Verifica o formato da hora hh:mm
 */
function horaIsOk(hora)
{
    return (/^([01][0-9]|2[0-3]):[0-5][0-9]$/).test(hora);
}

/**
 * Salva um valor num cookie
 */
function Set_Cookie( name, value, expires, path, domain, secure ) 
{
    // set time, it's in milliseconds
    var today = new Date();
    today.setTime(today.getTime());

    /*
    if the expires variable is set, make the correct 
    expires time, the current script below will set 
    it for x number of days, to make it for hours, 
    delete * 24, for minutes, delete * 60 * 24
    */
    if ( expires )
    {
        expires = expires * 1000 * 60 * 60 * 24;
    }
    var expires_date = new Date( today.getTime() + (expires) );

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

/**
 * Recupera o valor de um cookie
 */
function Get_Cookie(check_name)
{
    // first we'll split this cookie up into name/value pairs
    // note: document.cookie only returns name=value, not the other components
    var a_all_cookies = document.cookie.split(';');
    var a_temp_cookie = '';
    var cookie_name = '';
    var cookie_value = '';
    var b_cookie_found = false; // set boolean t/f default f

    for ( var i = 0; i < a_all_cookies.length; i++ )
    {
        // now we'll split apart each name=value pair
        a_temp_cookie = a_all_cookies[i].split('=');
        if ( a_temp_cookie.length != 2 ) continue;
        
        // and trim left/right whitespace while we're at it
        cookie_name = a_temp_cookie[0].trim();

        // if the extracted name matches passed check_name
        if ( cookie_name == check_name )
        {
            b_cookie_found = true;
            cookie_value = unescape(a_temp_cookie[1].trim());
            return cookie_value;
            break;
        }
        a_temp_cookie = null;
        cookie_name = '';
    }
    //if ( !b_cookie_found ) return '';
    
    return '';
}

/**
 * This deletes the cookie when called
 */
function Delete_Cookie( name, path, domain )
{
    if ( Get_Cookie( name ) )
        document.cookie = name + "=" +
        ( ( path ) ? ";path=" + path : "") +
        ( ( domain ) ? ";domain=" + domain : "" ) +
        ";expires=Thu, 01-Jan-1970 00:00:01 GMT";
}

/**
 * Posição do elemento em relação ao body
 * @param {Object} elm
 * @return {Object}
 */
function elmPosition(elm)
{
    
    var aTag = elm;
    var left = 0;
    var top = 0;
    do
    {
        aTag  = aTag.offsetParent;
        left += aTag.offsetLeft;
        top  += aTag.offsetTop;
        //aTag  = aTag.offsetParent;
    } while ( aTag.tagName.toUpperCase() != "BODY" );
    return {top: top, left: left};
    
    /*
    var elmLeft   = elm.offsetLeft;
    var elmTop    = elm.offsetTop;
    var elmParent = elm.offsetParent;
    
    while( elmParent.tagName.toUpperCase() != "BODY" )
    {
        elmLeft  += elmParent.offsetLeft;
        elmTop   += elmParent.offsetTop;
        elmParent = elmParent.offsetParent;
    }
    return {top: elmTop, left: elmLeft};
    */
}

/**
 * Posiciona um elemento em relação a outro, em cima, em baixo, na esquerda e direita
 * @param element objToAttach
 * @param element attachTo
 * @param string position (top, right, bottom, left)
 */
function attachElement(objToAttach, attachTo, position)
{
    objToAttach.style.position = "absolute";
    /*
    var
        aTag = attachTo,
        leftpos = 0,
        toppos = 0;
    do
    {
        aTag     = aTag.offsetParent;
        leftpos += aTag.offsetLeft;
        toppos  += aTag.offsetTop;
    } while ( aTag.tagName != "BODY" );
    */
    var pos = elmPosition(attachTo);
    var leftpos;
    var toppos;
    leftpos = pos.left;
    toppos = pos.top;
    
    switch ( position )
    {
        case 'up':
            objToAttach.style.top  = toppos  + attachTo.offsetTop - objToAttach.offsetHeight;
            objToAttach.style.left = leftpos + attachTo.offsetLeft;
            break;
        case 'down':
            objToAttach.style.top  = toppos  + attachTo.offsetTop + attachTo.offsetHeight;
            objToAttach.style.left = leftpos + attachTo.offsetLeft;
            break;
        case 'left':
            objToAttach.style.top  = toppos  + attachTo.offsetTop;
            objToAttach.style.left = leftpos + attachTo.offsetLeft - objToAttach.offsetWidth;
            break;
        case 'right':
            objToAttach.style.top  = toppos  + attachTo.offsetTop;
            objToAttach.style.left = leftpos + attachTo.offsetLeft + attachTo.offsetWidth;
            break;
        default:
            objToAttach.style.top  = 0;
            objToAttach.style.left = 0;
    }
}

/**
 * Retorna um array com os parâmetros da url (GET)
 * Se nenhum parâmetro for encontrado retorna um array vazio
 * @return Array
 */
function urlGetParams()
{
    var
        i, keyValue, get = new Array(),
        url = window.location.href,
        getParam = url.match(/\?(.+)/);
    if ( getParam == null ) return get;
    
    getParam = getParam[1];
    getParam = getParam.split('&');
    for ( i = 0; i < getParam.length; i++ )
    {
        keyValue = getParam[i].split('=');
        get[keyValue[0]] = keyValue[1];
    }
    return get;
}

/**
 * Junta uma certa quantidade de strings à esquerda ou direita da string de origem
 * Similar à função do PHP
 * @param string str (string de origem)
 * @param int numPad (número de repetições)
 * @param string strToPad (string a ser adicionada)
 * @param int direction (0: esquerda, 1: direita)
 * @return string
 */
function str_pad(str, numPad, strToPad, direction)
{
    str += '';
    while ( str.length < numPad )
    {
        if ( direction == 0 ) str = strToPad + str;
        else str += strToPad;
    }
    return str;
}

/**
 * Acrescenta zeros à esquerda
 * @param string str
 * @param int numPad
 * @return string
 */
function padLeft0(str, numPad)
{
    str += '';
    while ( str.length < numPad ) str = '0' + str;
    return str;
}

/**
 * Converte segundos no formato d hh:mm:ss
 * @param int tempo (em segundos)
 * @param bool microSeg (usar microsegundos)
 * @return string (d dias, hh:mm:ss,uuu)
 */
function secToTime(tempo, microSeg)
{
    if ( isNaN(tempo) ) return '';
    
    var
        sec     = microSeg ? 1000 : 1,
        secMin  = 60 * sec,
        secHour = 60 * secMin,
        secDay  = 24 * secHour;
    
    var timeElm = new Array(secDay, secHour, secMin, sec, 1);
    
    var tmp = tempo;
    var timeVal = new Array();
    var val;
    for ( var i = 0; i < timeElm.length; i++ )
    {
        val = timeElm[i];
        timeVal[i] = padLeft0(parseInt(tmp / val), 2);
        tmp = tmp % val;
    }
    
    var timeStr = "";
    if ( timeVal[0] > 0 )
        timeStr += parseInt(timeVal[0]) + " dia" + ((timeVal[0] == 1) ? '' : 's') + ", ";

    timeStr += timeVal.slice(1, 4).join(":") + (microSeg ? ("," + padLeft0(timeVal[5], 3)) : '');
    return timeStr;
}

/**
 * Converte uma string no formato d dias, hh:mm:ss,uuu para segundos
 * @param string timeStr
 * @return int
 */
function timeStrToSec(timeStr)
{
    var time = timeStr.match(/^(?:([0-9]+) dia[s]?, )?([0-9]{2}):([0-9]{2}):([0-9]{2})(?:,([0-9]{3}))?$/);
    if ( time == null ) return '';
    
    var
        microSec = !(isNaN(time[5]) || (time[5] == '')),
        sec     = microSec ? 1000 : 1,
        secMin  = 60 * sec,
        secHour = 60 * secMin,
        secDay  = 24 * secHour;
    
    var timeSec = (isNaN(time[1]) || (time[1] == '')) ? 0 : time[1] * secDay;
    timeSec += (time[2] * secHour)
        + (time[3] * secMin)
        + (time[4] * sec)
        + (microSec ? (time[5] * 1) : 0);
    
    return timeSec;
}

/**
 * Arredonda números
 * 
 * @param {Numeric} number
 * @param {Integer} decimals
 */
function round(number, decimals)
{
    number = '' + number;
    var parts, tmp;
    if ( (parts = number.match(/(\d*)\.(\d+)?/)) != null )
    {
        tmp = '';
        if ( parts[2].length > decimals )
        {
            tmp = parseInt(parts[2].charAt(decimals));
            parts[2] = parts[2].substring(0, decimals);
            if ( tmp > 4 )
            {
                if ( decimals == 0 )
                {
                    tmp = '';
                    if ( parts[1] == '' )
                        parts[1] = 0;
                    parts[1] = '' + (parseInt(parts[1]) + 1);
                }
                else
                    tmp = (parseInt(parts[2]) + 1);
            }
            else
                tmp = parts[2];
            tmp = '' + tmp;
        }
        else
            tmp = parts[2];
        while ( tmp.length < decimals )
            tmp += '0';
        number = parts[1]+(decimals > 0 ? '.'+tmp : '');
    }
    return number;
}

/**
 * Prefixos para kilo, Mega e Tera
 * @param {Numeric} size
 */
function fileSize(size)
{
    var i = 0, prefix = ' kMT';
    while ( size >= 1024 )
    {
        size /= 1024;
        i++;
    }
    return '' + round(size, 2) + ' ' + prefix.charAt(i);
}
