/**
 * Arquivo de Funções Padrões a todo o sistema
 *
 * @author Iuri Andreazza
 * @since 10/2006
 * @version 0.0.1-alpha
 */
 
function showNaoListado( object ){
	if(object.value == -2){
		showElement(document.forms['frm'].elements[object.name+'_naolistado']);
	}else{		
		hideElement(document.forms['frm'].elements[object.name+'_naolistado']);
	}
} 

/**
 * Função de enviar o Formulário e colocar uma Acao nos campos (nao nessesário)
 *
 * @param String Form (Nome do formulário)
 * @param String Action (String com o valor que irá passar no campo Acao)
 */
function postBack(form, action){
	document.forms[form].action += '?postBack=1';
	//O Uso do campo Acao nao é obrigatório.
	try{
	    if(action != ''){
	        document.forms[form].elements['acao'].value = action;
	    }
	}catch(ee){}
	
	document.forms[form].submit();
}
 
/**
 * Funcao que indica se o browser tem um popupbloquer ou não.
 *
 * @return boolean
 */ 
function detectPopupBlocker() {
  var myTest = window.open("about:blank","","directories=no,height=100,width=100,menubar=no,resizable=no,scrollbars=no,status=no,titlebar=no,top=0,location=no");
  if (!myTest) {
    return true;
  } else {
    myTest.close();
    return false;
  }
}
 
/**
 * Mostra Elementos Escondidos com CSS
 *
 * @param object (Objeto DOM)
 * @return boolean (Estado da Funcao [Caso Conseguiu mostrar o Elemento = true se nao volta false])
 */
function showElement( object ){
	var StatusFunction = false;
	try{
		object.style.visibility = 'visible';
		object.style.position   = 'fixed';
		StatusFunction = true;
	}catch(e){
		StatusFunction = false;
	}
	return StatusFunction;
}

/**
 * Esconde Elementos Visiveis com CSS
 *
 * @param object (Objeto DOM)
 * @return boolean (Estado da Funcao [Caso Conseguiu mostrar o Elemento = true se nao volta false])
 */
function hideElement( object ){
	var StatusFunction = false;
	try{
		object.style.visibility = 'hidden';
		object.style.position   = 'absolute';
		StatusFunction = true;
	}catch(e){
		StatusFunction = false;
	}
	return StatusFunction;
}


function isHided( object ){
	return (StatusFunction = false);
	try{
		if(object.style.visibility == 'hidden'){
			StatusFunction =  true;
		}
	}catch(e){
		StatusFunction = false;
	}
	return StatusFunction;
}

/**
 * int mktime([ int hour [, int minute [, int second [, int month [, int day [, int year [, int is_dst]]]]]]] )
 */

function mktime() {
    // http://kevin.vanzonneveld.net
    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // *     example 1: mktime( 14, 10, 2, 2, 1, 2008 );
    // *     returns 1: 1204377002
 
    var i = 0, d = new Date(), argv = arguments, argc = argv.length;
    var dateManip = {
        0: function(tt){ return d.setHours(tt); },
        1: function(tt){ return d.setMinutes(tt); },
        2: function(tt){ return d.setSeconds(tt); },
        3: function(tt){ return d.setMonth(tt); },
        4: function(tt){ return d.setDate(tt); },
        5: function(tt){ return d.setYear(tt); }
    };
 
    for( i = 0; i < argc; i++ ){
        if(argv[i] && isNaN(argv[i])){
            return false;
        } else if(argv[i]){
            // arg is number, let's manipulate date object
            if(!dateManip[i](argv[i])){
                // failed
                return false;
            }
        }
    }
 
    return Math.floor(d.getTime()/1000);
}

function urlDecode(str){
    str=str.replace(new RegExp('\\+','g'),' ');
    return unescape(str);
}
function urlEncode(str){
    
	str=escape(str);
    str=str.replace(new RegExp('\\+','g'),'%2B');
    str=str.replace(new RegExp('@','g'),'%40');
    str=str.replace(new RegExp('[*]','g'),'%2A');
	str=str.replace(new RegExp('[/]','g'),'%2F');
    return str.replace(new RegExp('%20','g'),'+');
}

var END_OF_INPUT = -1;

var base64Chars = new Array(
    'A','B','C','D','E','F','G','H',
    'I','J','K','L','M','N','O','P',
    'Q','R','S','T','U','V','W','X',
    'Y','Z','a','b','c','d','e','f',
    'g','h','i','j','k','l','m','n',
    'o','p','q','r','s','t','u','v',
    'w','x','y','z','0','1','2','3',
    '4','5','6','7','8','9','+','/'
);

var reverseBase64Chars = new Array();
for (var i=0; i < base64Chars.length; i++){
    reverseBase64Chars[base64Chars[i]] = i;
}

var base64Str;
var base64Count;
function setBase64Str(str){
    base64Str = str;
    base64Count = 0;
}
function readBase64(){    
    if (!base64Str) return END_OF_INPUT;
    if (base64Count >= base64Str.length) return END_OF_INPUT;
    var c = base64Str.charCodeAt(base64Count) & 0xff;
    base64Count++;
    return c;
}
function encodeBase64(str){
    setBase64Str(str);
    var result = '';
    var inBuffer = new Array(3);
    var lineCount = 0;
    var done = false;
    while (!done && (inBuffer[0] = readBase64()) != END_OF_INPUT){
        inBuffer[1] = readBase64();
        inBuffer[2] = readBase64();
        result += (base64Chars[ inBuffer[0] >> 2 ]);
        if (inBuffer[1] != END_OF_INPUT){
            result += (base64Chars [(( inBuffer[0] << 4 ) & 0x30) | (inBuffer[1] >> 4) ]);
            if (inBuffer[2] != END_OF_INPUT){
                result += (base64Chars [((inBuffer[1] << 2) & 0x3c) | (inBuffer[2] >> 6) ]);
                result += (base64Chars [inBuffer[2] & 0x3F]);
            } else {
                result += (base64Chars [((inBuffer[1] << 2) & 0x3c)]);
                result += ('=');
                done = true;
            }
        } else {
            result += (base64Chars [(( inBuffer[0] << 4 ) & 0x30)]);
            result += ('=');
            result += ('=');
            done = true;
        }
        lineCount += 4;
        if (lineCount >= 76){
            result += ('\n');
            lineCount = 0;
        }
    }
    return result;
}
function readReverseBase64(){   
    if (!base64Str) return END_OF_INPUT;
    while (true){      
        if (base64Count >= base64Str.length) return END_OF_INPUT;
        var nextCharacter = base64Str.charAt(base64Count);
        base64Count++;
        if (reverseBase64Chars[nextCharacter]){
            return reverseBase64Chars[nextCharacter];
        }
        if (nextCharacter == 'A') return 0;
    }
    return END_OF_INPUT;
}

function ntos(n){
    n=n.toString(16);
    if (n.length == 1) n="0"+n;
    n="%"+n;
    return unescape(n);
}

function decodeBase64(str){
    setBase64Str(str);
    var result = "";
    var inBuffer = new Array(4);
    var done = false;
    while (!done && (inBuffer[0] = readReverseBase64()) != END_OF_INPUT
        && (inBuffer[1] = readReverseBase64()) != END_OF_INPUT){
        inBuffer[2] = readReverseBase64();
        inBuffer[3] = readReverseBase64();
        result += ntos((((inBuffer[0] << 2) & 0xff)| inBuffer[1] >> 4));
        if (inBuffer[2] != END_OF_INPUT){
            result +=  ntos((((inBuffer[1] << 4) & 0xff)| inBuffer[2] >> 2));
            if (inBuffer[3] != END_OF_INPUT){
                result +=  ntos((((inBuffer[2] << 6)  & 0xff) | inBuffer[3]));
            } else {
                done = true;
            }
        } else {
            done = true;
        }
    }
    return result;
}

var digitArray = new Array('0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f');
function toHex(n){
    var result = ''
    var start = true;
    for (var i=32; i>0;){
        i-=4;
        var digit = (n>>i) & 0xf;
        if (!start || digit != 0){
            start = false;
            result += digitArray[digit];
        }
    }
    return (result==''?'0':result);
}

function pad(str, len, pad){
    var result = str;
    for (var i=str.length; i<len; i++){
        result = pad + result;
    }
    return result;
}

function encodeHex(str){
    var result = "";
    for (var i=0; i<str.length; i++){
        result += pad(toHex(str.charCodeAt(i)&0xff),2,'0');
    }
    return result;
}

function decodeHex(str){
    str = str.replace(new RegExp("s/[^0-9a-zA-Z]//g"));
    var result = "";
    var nextchar = "";
    for (var i=0; i<str.length; i++){
        nextchar += str.charAt(i);
        if (nextchar.length == 2){
            result += ntos(eval('0x'+nextchar));
            nextchar = "";
        }
    }
    return result;
    
}



function trocaClass(obj,clsName) {
	obj.className = clsName;
}






/**
 *
 *
 *
 */
 function SelectObject(idElement){
    this.elemento = document.getElementById(idElement);
    
    this.AddValue = function(Valor, Descricao, selecionado){
        id = this.elemento.options.length;
        this.elemento.options[id] = new Option(Descricao,Valor, false, false);
    }
    
    this.RemoveValue = function(Valor){
        var listOpt = this.elemento.options
        var valorSel = this.elemento.value;
        this.elemento.options.length = 0;
        for(var i = 0; i < listOpt.length; i ++ ){
            if(listOpt.value != Valor){
                var sel = false;
                if(listOpt.value == valorSel){
                    sel = true;
                }
                this.AddValue(listOpt.value, listOpt.innerHTML, sel);    
            }
        }
    }
    
    this.RemoveAll = function(){
        this.elemento.options.length = 1;
    }
 }
 
/**
 * Classe para manipular o checkboxList aonde permite 
 *
 *
 */
 function checkBoxList(){
    this.checksList = new Array();
    
    /**
     * Adiciona um CheckBox na lista (se ele nao existir)
     *
     * @param Checkbox Check
     */
    this.AddCheck = function(Check){
        // Nao tem um Check Com esse Id
        if(!this.find(Check.id)){
            this.checksList.push(Check);
        }
    }
    
    /**
     * Habilita Todos CheckBox na Lista
     *
     * @return void
     */
    this.EnableAll = function(){
        for( i = 0; i < this.checksList.length; i++){
             var check = this.getCheckbox(this.checksList[i].id);
             check.enable();
        }
    }
    
    /**
     * Desabilita Todos CheckBox na Lista
     *
     * @return void
     */
    this.DisableAll = function(){
        for( i = 0; i < this.checksList.length; i++){
             var check = this.getCheckbox(this.checksList[i].id);
             check.disable();
        }
    }
    
    /**
     * Habilita um unico CheckBox na Lista
     *
     * @param int checkId
     * @return void
     */
    this.Enable = function(checkId){
        var check = this.getCheckbox(checkId);
        check.enable();
    }
     
    /**
     * Desabilita um unico CheckBox na Lista
     *
     * @param int checkId
     * @return void
     */
    this.Disable = function(checkId){
        var check = this.getCheckbox(checkId);
        check.disable();
    }
    
    this.Check = function(checkId){
        var checkbox = this.getCheckbox(checkId);
        checkbox.check();
    }
    
    this.Uncheck = function(checkId){
        var checkbox = this.getCheckbox(checkId);
        checkbox.uncheck();
    }
    
    this.CheckAll = function(){
        for( i = 0; i < this.checksList.length; i++){
             var checkbox = this.getCheckbox(this.checksList[i].id);
             checkbox.check();
        }
    }
    
    this.UncheckAll = function(){
        for( i = 0; i < this.checksList.length; i++){
             var checkbox = this.getCheckbox(this.checksList[i].id);
             checkbox.uncheck();
        }
    }
    
    
    /**
     * Busca na listagem um CheckBox e retorna ele
     * 
     * @param int checkId (id do CheckBox)
     * @return CheckBox
     */
    this.getCheckbox = function(checkId){
        for( i = 0; i < this.checksList.length; i++){
 	        if(checkId == this.checksList[i].id){
 	            return this.checksList[i];
 	            break;
 	        }
 	    }
 	    
 	    return false;
    }
    
    /**
     * Procura por um id de um checkbox na listagem
     *
     * @return boolean
     * @param int checkId
     */
    this.find = function(checkId){
       var achou = false;
 	    for( i = 0; i < this.checksList.length; i++){
 	        if(checkId == this.checksList[i].id){
 	            achou = true;
 	            break;
 	        }
 	    }
 	    return achou;
    }
 }
 
 
 
 
 function checkbox(){
    this.id;
    this.name;
    this.value;
    this.label;
    this.onclickFunction;
    
    this.element = function(){
        return document.getElementById(this.id);
    }
    
    this.enable = function(){
        document.getElementById(this.id).disabled = false;
    }
    
    this.disable = function(){
        document.getElementById(this.id).disabled = true;
    }
    
    this.check = function(){
        document.getElementById(this.id).checked = true;
    }
    
    this.uncheck = function(){
        document.getElementById(this.id).checked = false;
    }
 }
 
 
 
 function spinBox(name){
 	this.name = name;
 	this.currentValue;
	this.minValue = -999999;
	this.maxValue = 999999;
	this.indentSize = 1;
	
	//Events
	this.onIncrement = function(){};
	this.onDecrement = function(){};
	this.beforeIncrement = function(){};
	this.beforeDecrement = function(){};
	this.onSetValue = function(){};
	
	this.Elem = document.createElement('INPUT');
	
	this.init = function(val, minVal, maxVal, indentSz){
		if(minVal != null && minVal != ''){
			this.minValue = minVal;
		}
		if(maxVal != null && minVal != ''){
			this.maxValue = maxVal;
		}
		this.indentSize = indentSz;
		this.setValue(val);
	}
	
	this.Inc = function(){
		this.beforeIncrement(this);
		this.setValue(parseInt(this.currentValue) + parseInt(this.indentSize));
		this.onIncrement(this);
	}
	
	this.Dec = function(){
		this.beforeDecrement(this);
		this.setValue(parseInt(this.currentValue) - parseInt(this.indentSize));
		this.onDecrement(this);
	}
	
	this.SetToMin = function(){
		this.setValue(parseInt(this.minValue));
	}
	
	this.SetToMax = function(){
		this.setValue(parseInt(this.maxValue));
	}
	
	this.Draw = function(containerId){
		var container = document.getElementById(containerId);
		this.Elem.SpinObject = this;
		this.Elem.name = this.name;
		this.Elem.id = this.name;
		this.Elem.value = this.currentValue;
		this.Elem.type = 'text';
		this.Elem.onchange = function(){
			this.SpinObject.setValue(parseInt(this.value));
		}
		
		
		var btnUp  = document.createElement('INPUT');
		btnUp.type = "button";
		btnUp.value = "";
		btnUp.style.fontSize = '0';
		
		btnUp.style.width = '25';
		btnUp.style.height = '11';		
		if(!document.all){
			//FF
			btnUp.style.left = "-20px";
			btnUp.style.top = "-8px";
		}else{
			//IE
			btnUp.style.left = "-24px";
			btnUp.style.top = "-9px";
		}
		btnUp.style.verticalAlign = "bottom";
		btnUp.style.position = "relative";
		
		
		btnUp.SpinObject = this;
		
		btnUp.onclick = function(){
			this.SpinObject.Inc();
		}

		
		var btnDw = document.createElement('INPUT');
		btnDw.type = "button";
		btnDw.value = "";
		btnDw.style.fontSize = '0';
		btnDw.style.margin = '0'
		btnDw.style.width = '25';
		btnDw.style.height = '11';

		btnDw.style.verticalAlign = "bottom";
		
		btnDw.style.position = "relative";
		
		if(!document.all){
			//FF
			btnDw.style.left = "-40px";
			btnDw.style.top = "0px";
		}else{
			//IE
			btnDw.style.left = "-49px";
			btnDw.style.top = "0px";
		}
		
		btnDw.SpinObject = this;
		btnDw.onclick = function(){
			this.SpinObject.Dec();
		}
		
		var spanContainer = document.createElement('SPAN');
		
		spanContainer.appendChild(this.Elem);
		spanContainer.appendChild(btnUp);
		spanContainer.appendChild(btnDw);
		
		container.appendChild(spanContainer);
	}
	
	this.setValue = function(val){
		if(val >= this.minValue & val <= this.maxValue){
			this.currentValue = val;
		}else{
			if(val < this.minValue){
				this.currentValue = this.minValue;
			} else if (val > this.maxValue){
				this.currentValue = this.maxValue;
			}else{
				this.currentValue = 0;
			}
		}
		this.Elem.value = this.currentValue;
		this.onSetValue(this);
	}
	
	this.onInc = function(func){
		this.onIncrement = func;
	}
	
	this.onDec = function(func){
		this.onDecrement = func;
	}
	
	this.BeforeInc = function(func){
		this.beforeIncrement = func;
	}
	
	this.BeforeDec = function(func){
		this.beforeDecrement = func;
	}
	
	this.onSetVal = function(func){
		this.onSetValue = func;
	}
	
 }
 
 
 
/**
 *
 *
 */

function hashFormulario(formName,panelExt){
	if(panelExt){
		el = panelExt.getForm().getEl();
		formName = el.id;
		
	}
	var formulario = document.forms[formName];
	var strVal = '';
	var enctype = formulario.enctype;
	
	//Verifica se já existe o campo do hash no form e o remove
	if(document.forms[formName].elements['form_key']!=null){
		document.forms[formName].removeChild(document.forms[formName].elements['form_key']);
	}
	
	for(var i = 0; i < formulario.length; i++){
		if(formulario[i].name != null && formulario[i].name != '' && (formulario[i].disabled == false || formulario[i].disabled == null)){
			switch(formulario[i].type){
				case 'radio':
				case 'checkbox':
					if(formulario[i].checked == true){
						strVal += formulario[i].value;
					}
					break;
				case 'select-multiple':
					break;
				case 'file':
					if(enctype != 'multipart/form-data'){
						var t = formulario[i].value;
						t = t.replace(/\\/gi,'\\\\')
						t = t.replace(/\//gi,'\\\\')
						strVal += t;
					}
					break;
				default:
					strVal += formulario[i].value;
					break;
			}
		}
	}
	
	var formKey = createFormKey(strVal);
	
	if(document.forms[formName].elements[formKey.name] != null){
		document.forms[formName].elements[formKey.name].value = formKey.value;
	}else{
		document.forms[formName].appendChild(formKey);
	}
	if(panelExt){
		ret = formKey.value;
	}else{
		ret = true;
	}
	return ret;
}

function createFormKey(strVal){
	var formKey = document.createElement('INPUT');
	formKey.type = 'hidden';
	formKey.value = hex_sha1(urlEncode(strVal));
	formKey.name = 'form_key';
	formKey.id = 'form_key';
	
	return formKey;
}

function createExtAjaxFormKey(o){
	var str = '', ret = {}, keyObj = null;

	for (p in o.hashParams){
		ret[p] = o.hashParams[p];
		str += o.hashParams[p];
	}

	keyObj = createFormKey(str);
	ret[keyObj.name] = keyObj.value; 

	return ret;
}

function executaAcao(formName, viewName, method){
	document.forms[formName].elements[viewName+'[method]'].value = method;
	hashFormulario(formName);
	document.forms[formName].submit();
}

//Captura de eventos
if (document.layers) { // Netscape
    document.captureEvents(Event.MOUSEMOVE);
    document.onmousemove = captureMousePosition;
} else if (document.all) { // Internet Explorer
    document.onmousemove = captureMousePosition;
} else if (document.getElementById) { // Netcsape 6
    document.onmousemove = captureMousePosition;
}
// Global variables
xMousePos = 0; // Horizontal position of the mouse on the screen
yMousePos = 0; // Vertical position of the mouse on the screen
xMousePosMax = 0; // Width of the page
yMousePosMax = 0; // Height of the page

function captureMousePosition(e) {
	try{
	    if (document.layers) {
	        // When the page scrolls in Netscape, the event's mouse position
	        // reflects the absolute position on the screen. innerHight/Width
	        // is the position from the top/left of the screen that the user is
	        // looking at. pageX/YOffset is the amount that the user has
	        // scrolled into the page. So the values will be in relation to
	        // each other as the total offsets into the page, no matter if
	        // the user has scrolled or not.
	        xMousePos = e.pageX;
	        yMousePos = e.pageY;
	        xMousePosMax = window.innerWidth+window.pageXOffset;
	        yMousePosMax = window.innerHeight+window.pageYOffset;
	    } else if (document.all) {
	        // When the page scrolls in IE, the event's mouse position
	        // reflects the position from the top/left of the screen the
	        // user is looking at. scrollLeft/Top is the amount the user
	        // has scrolled into the page. clientWidth/Height is the height/
	        // width of the current page the user is looking at. So, to be
	        // consistent with Netscape (above), add the scroll offsets to
	        // both so we end up with an absolute value on the page, no
	        // matter if the user has scrolled or not.
	        xMousePos = window.event.x+document.body.scrollLeft;
	        yMousePos = window.event.y+document.body.scrollTop;
	        xMousePosMax = document.body.clientWidth+document.body.scrollLeft;
	        yMousePosMax = document.body.clientHeight+document.body.scrollTop;
	    } else if (document.getElementById) {
	        // Netscape 6 behaves the same as Netscape 4 in this regard
	        xMousePos = e.pageX;
	        yMousePos = e.pageY;
	        xMousePosMax = window.innerWidth+window.pageXOffset;
	        yMousePosMax = window.innerHeight+window.pageYOffset;
	    }
    }catch(e){}
}



function getPageSize(){
	var body;
	//HACK FF 3 (COISA PODRE NAO TEM ACESSO DIRETO)
	if(document.body == null){
		body = document.getElementsByTagName('body')[0];
	}else{
		body = document.body;
	}
	var xScroll, yScroll;
	if (window.innerHeight && window.scrollMaxY) {	
		xScroll = body.scrollWidth;
		yScroll = window.innerHeight + window.scrollMaxY;
	} else if (body.scrollHeight > body.offsetHeight){ // all but Explorer Mac
		xScroll = body.scrollWidth;
		yScroll = body.scrollHeight;
	} else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
		xScroll = body.offsetWidth;
		yScroll = body.offsetHeight;
	}
	var windowWidth, windowHeight;
	if (self.innerHeight) {	// all except Explorer
		windowWidth = self.innerWidth;
		windowHeight = self.innerHeight;
	} else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
		windowWidth = document.documentElement.clientWidth;
		windowHeight = document.documentElement.clientHeight;
	} else if (document.body) { // other Explorers
		windowWidth = document.body.clientWidth;
		windowHeight = document.body.clientHeight;
	}	
	// for small pages with total height less then height of the viewport
	if(yScroll < windowHeight){
		pageHeight = windowHeight;
	} else { 
		pageHeight = yScroll;
	}

	// for small pages with total width less then width of the viewport
	if(xScroll < windowWidth){	
		pageWidth = windowWidth;
	} else {
		pageWidth = xScroll;
	}
	arrayPageSize = new Array(pageWidth,pageHeight,windowWidth,windowHeight);
}

var timer;

function bodyOverlay() {
	  var objBody = document.getElementsByTagName('body').item(0);
	  var sizesPage = getPageSize();
	  var bodyOverlay = document.createElement("div");
	  bodyOverlay.setAttribute('id','bodyOverlay');
	  bodyOverlay.style.height = arrayPageSize[1] + 'px'; // fundo com o tamanho total da página.
	  if (!document.getElementById('bodyOverlay')) {
		    objBody.insertBefore(bodyOverlay, objBody.firstChild);
	  }
}

function removerOverlay() {
	  var bodyOverlay = document.getElementById('bodyOverlay');
	  if (bodyOverlay) {
		    bodyOverlay.parentNode.removeChild(bodyOverlay);
	  }
}


 function highlightCampo(obj){
    obj.offsetParent.style.border = '1px solid #000';
    obj.offsetParent.Parcial;
 }
 
 function unhighlightCampo(obj){
    obj.offsetParent.style.border = '0px solid #000';
 }



function rand ( n )
{
  return ( Math.floor ( Math.random ( ) * n + 1 ) );
}




/*
 * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined
 * in FIPS PUB 180-1
 * Version 2.1a Copyright Paul Johnston 2000 - 2002.
 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
 * Distributed under the BSD License
 * See http://pajhome.org.uk/crypt/md5 for details.
 */

/*
 * Configurable variables. You may need to tweak these to be compatible with
 * the server-side, but the defaults work in most cases.
 */
var hexcase = 0;  /* hex output format. 0 - lowercase; 1 - uppercase        */
var b64pad  = ""; /* base-64 pad character. "=" for strict RFC compliance   */
var chrsz   = 8;  /* bits per input character. 8 - ASCII; 16 - Unicode      */

/*
 * These are the functions you'll usually want to call
 * They take string arguments and return either hex or base-64 encoded strings
 */
function hex_sha1(s){return binb2hex(core_sha1(str2binb(s),s.length * chrsz));}
function b64_sha1(s){return binb2b64(core_sha1(str2binb(s),s.length * chrsz));}
function str_sha1(s){return binb2str(core_sha1(str2binb(s),s.length * chrsz));}
function hex_hmac_sha1(key, data){ return binb2hex(core_hmac_sha1(key, data));}
function b64_hmac_sha1(key, data){ return binb2b64(core_hmac_sha1(key, data));}
function str_hmac_sha1(key, data){ return binb2str(core_hmac_sha1(key, data));}

/*
 * Perform a simple self-test to see if the VM is working
 */
function sha1_vm_test()
{
  return hex_sha1("abc") == "a9993e364706816aba3e25717850c26c9cd0d89d";
}

/*
 * Calculate the SHA-1 of an array of big-endian words, and a bit length
 */
function core_sha1(x, len)
{
  /* append padding */
  x[len >> 5] |= 0x80 << (24 - len % 32);
  x[((len + 64 >> 9) << 4) + 15] = len;

  var w = Array(80);
  var a =  1732584193;
  var b = -271733879;
  var c = -1732584194;
  var d =  271733878;
  var e = -1009589776;

  for(var i = 0; i < x.length; i += 16)
  {
    var olda = a;
    var oldb = b;
    var oldc = c;
    var oldd = d;
    var olde = e;

    for(var j = 0; j < 80; j++)
    {
      if(j < 16) w[j] = x[i + j];
      else w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
      var t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)),
                       safe_add(safe_add(e, w[j]), sha1_kt(j)));
      e = d;
      d = c;
      c = rol(b, 30);
      b = a;
      a = t;
    }

    a = safe_add(a, olda);
    b = safe_add(b, oldb);
    c = safe_add(c, oldc);
    d = safe_add(d, oldd);
    e = safe_add(e, olde);
  }
  return Array(a, b, c, d, e);

}

/*
 * Perform the appropriate triplet combination function for the current
 * iteration
 */
function sha1_ft(t, b, c, d)
{
  if(t < 20) return (b & c) | ((~b) & d);
  if(t < 40) return b ^ c ^ d;
  if(t < 60) return (b & c) | (b & d) | (c & d);
  return b ^ c ^ d;
}

/*
 * Determine the appropriate additive constant for the current iteration
 */
function sha1_kt(t)
{
  return (t < 20) ?  1518500249 : (t < 40) ?  1859775393 :
         (t < 60) ? -1894007588 : -899497514;
}

/*
 * Calculate the HMAC-SHA1 of a key and some data
 */
function core_hmac_sha1(key, data)
{
  var bkey = str2binb(key);
  if(bkey.length > 16) bkey = core_sha1(bkey, key.length * chrsz);

  var ipad = Array(16), opad = Array(16);
  for(var i = 0; i < 16; i++)
  {
    ipad[i] = bkey[i] ^ 0x36363636;
    opad[i] = bkey[i] ^ 0x5C5C5C5C;
  }

  var hash = core_sha1(ipad.concat(str2binb(data)), 512 + data.length * chrsz);
  return core_sha1(opad.concat(hash), 512 + 160);
}

/*
 * Add integers, wrapping at 2^32. This uses 16-bit operations internally
 * to work around bugs in some JS interpreters.
 */
function safe_add(x, y)
{
  var lsw = (x & 0xFFFF) + (y & 0xFFFF);
  var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
  return (msw << 16) | (lsw & 0xFFFF);
}

/*
 * Bitwise rotate a 32-bit number to the left.
 */
function rol(num, cnt)
{
  return (num << cnt) | (num >>> (32 - cnt));
}

/*
 * Convert an 8-bit or 16-bit string to an array of big-endian words
 * In 8-bit function, characters >255 have their hi-byte silently ignored.
 */
function str2binb(str)
{
  var bin = Array();
  var mask = (1 << chrsz) - 1;
  for(var i = 0; i < str.length * chrsz; i += chrsz)
    bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (32 - chrsz - i%32);
  return bin;
}

/*
 * Convert an array of big-endian words to a string
 */
function binb2str(bin)
{
  var str = "";
  var mask = (1 << chrsz) - 1;
  for(var i = 0; i < bin.length * 32; i += chrsz)
    str += String.fromCharCode((bin[i>>5] >>> (32 - chrsz - i%32)) & mask);
  return str;
}

/*
 * Convert an array of big-endian words to a hex string.
 */
function binb2hex(binarray)
{
  var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
  var str = "";
  for(var i = 0; i < binarray.length * 4; i++)
  {
    str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) +
           hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8  )) & 0xF);
  }
  return str;
}

/*
 * Convert an array of big-endian words to a base-64 string
 */
function binb2b64(binarray)
{
  var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  var str = "";
  for(var i = 0; i < binarray.length * 4; i += 3)
  {
    var triplet = (((binarray[i   >> 2] >> 8 * (3 -  i   %4)) & 0xFF) << 16)
                | (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 )
                |  ((binarray[i+2 >> 2] >> 8 * (3 - (i+2)%4)) & 0xFF);
    for(var j = 0; j < 4; j++)
    {
      if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
      else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
    }
  }
  return str;
}

//------------------------------------------------------------------------------------------------------------------------------
 
/**
 * Funcões de Formatação Numérica
 * 
 */
 function amf2005_BecameInteger(val,len)
{
	n='__0123456789';
	d=val.value;
	l=d.length;
	s='';
	if (l > 0)
	{
		a=2;
		for (i=0; i<l; i++)
		{
			c=d.charAt(i);
			if (n.indexOf(c) > a)
			{
				a=1;
				s+=c;
			};
		};
		l=s.length;
		t=len-1;
		if (l > t)
		{
			l=t;
			s=s.substr(0,t);
		};
		if (s == '')
		{
			s='0';
		};
	};
	val.value=s;
	return 'ok';
};

function amf2005_BecameCurrency(cur,len)
{
   n='__0123456789';
   d=cur.value;
   l=d.length;
   r='';
   if (l > 0)
   {
	z=d.substr(0,l-1);
	s='';
	a=2;
	for (i=0; i < l; i++)
	{
		c=d.charAt(i);
		if (n.indexOf(c) > a)
		{
			a=1;
			s+=c;
		};
	};
	l=s.length;
	t=len-1;
	if (l > t)
	{
		l=t;
		s=s.substr(0,t);
	};
	if (l > 2)
	{
		r=s.substr(0,l-2)+','+s.substr(l-2,2);
	}
	else
	{
		if (l == 2)
		{
			r='0,'+s;
		}
		else
		{
			if (l == 1)
			{
				r='0,0'+s;
			};
		};
	};
	if (r == '')
	{
//		r='0,00';
		r='';
	}
	else
	{
		l=r.length;
		if (l > 6)
		{
			j=l%3;
			w=r.substr(0,j);
			wa=r.substr(j,l-j-6);
			wb=r.substr(l-6,6);
			if (j > 0)
			{
				w+='.';
			};
			k=(l-j)/3-2;
			for (i=0; i < k; i++)
			{
				w+=wa.substr(i*3,3)+'.';
			};
			r=w+wb;
		};
	};
   };
   if (r.length <= len)
   {
	cur.value=r;
   }
   else
   {
	cur.value=z;
   };
   return 'ok';
};

function amf2005_BecameNumber(val,len)
{
	n='__0123456789';
	d=val.value;
	l=d.length;
	s='';
	a=2;
	for (i=0; i<l; i++)
	{
		c=d.charAt(i);
		if (n.indexOf(c) > a)
		{
			a=1;
			s+=c;
		};
	};
	l=s.length;
	t=len-1;
	if (l > t)
	{
		l=t;
		s=s.substr(0,t);
	};
	r='';
	if (l > 2)
	{
		r=s.substr(0,l-2)+','+s.substr(l-2,2);
	}
	else
	{
		if (l == 2)
		{
			r='0,'+s;
		}
		else
		{
			if (l == 1)
			{
				r='0,0'+s;
			};
		};
	};
	if (r == '')
	{
		r='0,00';
	};
	val.value=r;
	return 'ok';
};


function amf2005_BecameFloat(val,len)
{
	n='__0123456789';
	d=val.value;
	l=d.length;
	s='';
	a=2;
	for (i=0; i<l; i++)
	{
		c=d.charAt(i);
		if (n.indexOf(c) > a)
		{
			a=1;
			s+=c;
		};
	};
	l=s.length;
	t=len-2;
	if (l > t)
	{
		l=t;
		s=s.substr(0,t);
	};
	r='';
	if (l > 2)
	{
		r=s.substr(0,l-2)+'.'+s.substr(l-2,2);
	}
	else
	{
		if (l == 2)
		{
			r='0.'+s;
		}
		else
		{
			if (l == 1)
			{
				r='0.0'+s;
			};
		};
	};
	if (r == '')
	{
		r='0.00';
	};
	val.value=r;
	return 'ok';
};

function amf2005_valid_date(l,dd,mm,yy)
{
	z='err';
	if (l == 6 || l == 8)
	{
		xx=yy;
		if (dd >= 1 && dd <= 31)
		{
			if (mm == 2 || mm == 4 || mm == 6 || mm == 9 || mm == 11)
			{
				if (dd <= 30)
				{
					if (mm == 2)
					{
						if (dd <= 28)
						{
							z='ok';
						}
						else
						{
							if (dd == 29)
							{
								bb=xx%4;	// 4 by 4
								if (bb == 0)
								{
									cc=xx%100;	// 100 by 100
									if (cc == 0)
									{
										qq=xx%400;	// 400 by 400
										if (qq == 0)
										{
											z='ok';
										};
									}
									else
									{
										z='ok';
									};	
								};
							};
						};
					}
					else
					{
						z='ok';
					};
				};
			}
			else
			{
				if (mm >= 1 && mm <= 12) { z='ok'; };
			};
		};
	};
	ii=200;		// inner parameter
	if (xx < 1600 || xx > 2400 || xx < 2005 - ii || xx > 2005 + ii) { z='err'; };
	return z;
};

function amf2005_consist_date(dat)
{
	n='0123456789';
	d=dat.value;
	l=d.length;
	s='';
	for (i=0; i<l; i++)
	{
		c=d.charAt(i);
		if (n.indexOf(c) >= 0)
		{
			s+=c;
		};
	};
	l=s.length;
	xx='0000';
	r=s;
	if (l > 8)
	{
		r=s.substr(0,8);
		s=r;
		l=8;
	};
	if (l == 6)
	{
		dd=s.substr(0,2);
		mm=s.substr(2,2);
		yy=s.substr(4,2);
		if (yy < 50)
		{
			xx='20'+yy;
		}
		else
		{
			xx='19'+yy;
		};
		ww=dd+'/'+mm+'/'+yy;
	};
	if (l == 8)
	{
		dd=s.substr(0,2);
		mm=s.substr(2,2);
		yy=s.substr(4,4);
		xx=yy;
		ww=dd+'/'+mm+'/'+yy;
	};
	if (l == 6 || l == 8)
	{
		z=amf2005_valid_date(l,dd,mm,xx);
		if (z == 'ok') { r=ww; };
	};
	dat.value=r;
	return 'ok';
};

function amf2005_update_date(dat)
{
	n='0123456789';
	d=dat.value;
	l=d.length;
	s='';
	for (i=0; i<l; i++)
	{
		c=d.charAt(i);
		if (n.indexOf(c) >= 0)
		{
			s+=c;
		};
	};
	l=s.length;
	if (l == 6)
	{
		dd=s.substr(0,2);
		mm=s.substr(2,2);
		yy=s.substr(4,2);
		if (yy < 50)
		{
			yy='20'+yy;
		}
		else
		{
			yy='19'+yy;
		};
		ww=dd+'/'+mm+'/'+yy;
	};
	if (l == 8)
	{
		dd=s.substr(0,2);
		mm=s.substr(2,2);
		yy=s.substr(4,4);
		ww=dd+'/'+mm+'/'+yy;
	};
	rr='';
	if (l == 6 || l == 8)
	{
		z=amf2005_valid_date(l,dd,mm,yy);
		if (z == 'ok')
		{ 
			rr=ww;
		};
	};
	dat.value=rr;
	return 'ok';
};

/**
 * Função para avaliar se uma string contem caracteres tipicos de script injection
 * @param {} str
 * @return {}
 */
function checkScriptInjection(str){
	var regexp = new RegExp('(<|>)|(script)|(\')|(\")', 'g');
	return regexp.test(str);
}

/**
 * Cria e retorna um ToolTip para exibir os dados e foto do aluno
 * 
 * @param {Ext.grid.GridPanel} grid grid onde exibir o tooltip
 * @param {Integer} colShow coluna onde exibir o tooltip com o mouse sobre
 * @param {Object} dataDictionary dicionario com os nomes dos campos do store do grid
 * @param {Array} filters array com os nomes dos campos, no store, enviados como parâmetros para a view
 * @return Ext.ToolTip
 * 
 * TODO: transformar esta função em um componente do ExtJs, extendendo Ext.ToolTip
 */
function createToolTipAluno(grid, colShow, dataDictionary, filters) {
    //adiciona o valor padrao a 'filters', caso seja vazio (para manter compatibilidade)
    if ( Ext.isEmpty(filters) ) {
        filters = ['codigoAluno'];
    }
    
    //adicionados eventos pro Tooltip seguir o mouse no FF
    Ext.ToolTip.prototype.onTargetOver = Ext.ToolTip.prototype.onTargetOver.createInterceptor(function(e) {
        this.baseTarget = e.getTarget();
    });
    Ext.ToolTip.prototype.onMouseMove = Ext.ToolTip.prototype.onMouseMove.createInterceptor(function(e) {
        if (this.baseTarget != null) {
            if (!e.within(this.baseTarget)) {
                this.onTargetOver(e);
                return false;
            }
        }
    });

    //Template para exibir as fotos e informações dos alunos
    var tplToolTipAluno = new Ext.Template(
        '<table><tr>',
            '<td><img width="60" ',
                    'src="fotoPessoa.php5?ViewFotoPessoaXmlXsl[method]=imprimeFotoAluno&{queryString}" /></td>',
            '<td style="font-weight: bold; vertical-align: top;"><p>{nomeAluno}</p></td>',
        '</tr></table>'
    );
    
    //define o "alvo" a vincular com o tooltip, dependendo do tipo de componente ou view
    if (grid.view.constructor == Ext.grid.LockingGridView) {
        var tipTarget = grid.view.lockedBody;
    } else {
        var tipTarget = grid.view.mainBody;
    }
    
    //retorna o Tooltip usando o template com os dados do aluno
    return new Ext.ToolTip({
        renderTo : Ext.getBody(),
        width : 280,
        target : tipTarget,
        trackMouse: true,
        dismissDelay : 10000,
        listeners : {
            beforeshow : function(me) {
                var v = this.getView();
                var row = v.findRowIndex(me.baseTarget);
                var col = v.findCellIndex(me.baseTarget);

                //correção para não exibir o tooltip nas colunas incorretas
                if (col != colShow && me.hidden) {
                    return false;
                }
                
                //cria o objeto params, para usar na query string
                var params = {};
                for (i = 0; i < filters.length; i++) {
                    fname = filters[i];
                    //se filtro estiver no dicionário, obtém o nome usado no store a partir dele,
                    //caso contrário, usa o próprio nome do filtro
                    if (! Ext.isEmpty( dataDictionary[fname] ) ) {
                        params[fname] = grid.getStore().getAt(row).get( dataDictionary[fname] );
                    } else {
                        params[fname] = grid.getStore().getAt(row).get( fname );
                    }
                }

                //objeto com os dados necessários ao Template
                var dados = {
                    queryString: Ext.urlEncode( params ),
                    nomeAluno  : grid.getStore().getAt(row).get( dataDictionary.nomeAluno )
                };

                //delay, para evitar bug do IE que oculta o tooltip qdo não devia. - MSIE sux ¬¬
                //e também para evitar overload caso alguém fique passando o mouse sobre o grid feito louco...
                new Ext.util.DelayedTask().delay(10, function(me, colShow, dados){
                    if (col == colShow) {
                        tplToolTipAluno.overwrite(me.body, dados);
                    } else {
                        me.hide();
                        return false;
                    }
                }, this, [me, colShow, dados]);
            },
            scope : grid
        }
    });
}

/**
 * Função para enviar requests a fim de manter sessão ativa
 */
function requestMantemSessaoAtiva(){
	var runnerMantemSessaoAtiva = new Ext.util.TaskRunner();
        runnerMantemSessaoAtiva.start({
            run: function() {
                Ext.Ajax.request({
                    url   : '../../actions.php5',
                    method: 'GET',
                    params: {'action': 'mantemSessaoAtiva'}
                });
            },
            interval: (1000 * 60 * 4) // 4 minutos entre cada chamada
        });
}

/**
 * Seta um delay de 15 segundos e "agenda" requests através do requestMantemSessaoAtiva
 */
function mantemSessaoAtiva(){
	taskSessaoAtiva = new Ext.util.DelayedTask(requestMantemSessaoAtiva); 
 	taskSessaoAtiva.delay(1000 * 5); // Delay de 15 segundos para iniciar 
}

