
/*
 * DIREITOS AUTORAIS RESERVADOS (C) 2007 UFRJ
 * 
 * ESTE PROGRAMA É SOFTWARE LIVRE; VOCÊ PODE REDISTRIBUÍ-LO E/OU MODIFICÁ-LO SOB OS
 * TERMOS DA LICENÇA PÚBLICA GERAL GNU CONFORME PUBLICADA PELA FREE SOFTWARE FOUNDATION;
 * TANTO A VERSÃO 2 DA LICENÇA, COMO (A SEU CRITÉRIO) QUALQUER VERSÃO POSTERIOR.

 * ESTE PROGRAMA É DISTRIBUÍDO NA EXPECTATIVA DE QUE SEJA ÚTIL, PORÉM, SEM NENHUMA GARANTIA;
 * NEM MESMO A GARANTIA IMPLÍCITA DE COMERCIABILIDADE OU ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA.
 * CONSULTE A LICENÇA PÚBLICA GERAL DO GNU PARA MAIS DETALHES.
 * 
 * VOCÊ DEVE TER RECEBIDO UMA CÓPIA DA LICENÇA PÚBLICA GERAL DO GNU JUNTO COM ESTE PROGRAMA; 
 * SE NÃO, ACESSE <<HTTP://WWW.GNU.ORG/LICENSES/LICENSES.PT-BR.HTML>>
 */

function AssertException(message) //{{{
{ 
	this.message = message; 
}//}}}
AssertException.prototype.toString = function () //{{{
{
	return 'AssertException: ' + this.message;
}//}}}
function assert(exp, message) //{{{
{
	if(!exp)
	{
		var aux;
		aux();

		if(!message)
			message = 'Assertion error';

		throw new AssertException(message);
	}
}//}}}

function erro_ajax(status, e)//{{{
{
	switch(status)
	{
	case 'parsererror':
		return 'Erro ao processar resposta do servidor';
	case 'timeout':
		return 'Tempo para resposta do servidor expirou';
	case 'notmodified':
		return 'notmodified';
	case 'erro':
		return 'Erro na resposta do servidor';
	default:
		if(e)
			return e.description;
		else
			// TODO: tah caindo aqui com alguma frequencia... ver o que eh
			return;
//		else
//			return 'Erro não previsto: '+status;
	}
}//}}}

function mostra_mensagem(msg, class_, autohide)//{{{
{
	var msgdisp = $('#message');

	if(msg == '')
		msgdisp.fadeOut('slow');
	else
	{
		msgdisp.attr('class',class_);
		msgdisp.html(msg);
		if(autohide)
		{
			msgdisp.fadeIn('slow', function() { 
				setTimeout("$('#message').fadeOut('slow')",2000); 
			});
		}
		else
			msgdisp.fadeIn('slow');
	}
}//}}}
function mostra_erro(msg)//{{{
{
	mostra_mensagem(msg, 'erro');
}//}}}
function mostra_sucesso(msg)//{{{
{
	mostra_mensagem(msg, 'sucesso', true);
}///}}}

function cns_valido(codigo)//{{{
{
	if(codigo.length != 18)
		return false;

	codigo = codigo.substr(0,3)+codigo.substr(4,4)+
			 codigo.substr(9,4)+codigo.substr(14,4);

	if(isNaN(Number(codigo)))
	   return false;

	var igual = true;
	for(var i=1; i<15; ++i)
	{
		if(codigo[i] != codigo[i-1])
		{
			igual = false;
			break;
		}
	}
	if(igual)
		return false;

	// Eh o cartão é o definitivo?
	if (codigo.charAt(0) != '8' && codigo.charAt(0) != '9')
	{
		// O número é formado a partir do número do PIS
		var pis = codigo.substr(0,11);
		var soma = 0;
		for(var i=0; i<11; ++i)
			soma += Number(pis.charAt(i)) * (15-i);
			
		var dv = 11 - soma % 11;
		if(dv == 11)
			dv = 0;

		if(dv == 10)
		{
			soma += 2;
			dv = 11 - soma % 11;
			resultado = pis + "001" + dv;
		}
		else
			resultado = pis + "000" + dv;

		if(codigo != resultado)
			return false;
	}
	// É o provisório?
	else
	{
		var soma = 0;
		for(var i=0; i<15; ++i)
			soma += Number(codigo.charAt(i)) * (15-i);

		dv = soma % 11;
		if (dv != 0)
			return false;
	}

	return true;
}//}}}
function cpf_valido(codigo)//{{{
{
	if(codigo.length != 14)
		return false;

	codigo = codigo.substr(0,3)+codigo.substr(4,3)+
			 codigo.substr(8,3)+codigo.substr(12,2);

	if(isNaN(Number(codigo)))
		return false;

	if(codigo == '00000000000' ||
	   codigo == '11111111111' ||
	   codigo == '22222222222' ||
	   codigo == '33333333333' ||
	   codigo == '44444444444' ||
	   codigo == '55555555555' ||
	   codigo == '66666666666' ||
	   codigo == '77777777777' ||
	   codigo == '88888888888' ||
	   codigo == '99999999999')
	{
		return false;
	}

	var dv1, dv2;

	dv1 = 0;
	for(var i=0; i<9; ++i)
		dv1 += Number(codigo.charAt(i)) * (10-i);

	dv1 = 11 - dv1 % 11;
	if(dv1 >= 10)
		dv1 = 0;

	dv2 = 2*dv1;
	for(var i=0; i<9; ++i)
		dv2 += Number(codigo.charAt(i)) * (11-i);

	dv2 = 11 - dv2 % 11;
	if (dv2 >= 10)
		dv2 = 0;

	return dv1==codigo.charAt(9) && dv2==codigo.charAt(10);
}//}}}

function keys(o)//{{{
{
	var arr = [];
	for(var key in o)
		arr.push(key);
	return arr;
}//}}}
function values(o)//{{{
{
	var arr = [];
	for(var key in o)
		arr.push(o[key]);
	return arr;
}//}}}

function percent(val, total)//{{{
{
	if(total == 0)
		return '0%';
	else
		return Math.round(val/total*1000)/10+'%';
}//}}}

document.write("<script type='text/javascript' src='js/jquery.json.js'></script>\n");

// Sistema de autosave
(function($) {
	$.fn.autosave = function(options)//{{{
	{
		if(this.length == 0)
			return false;

		var form = $(this[0]).is('form') ? this[0] : this[0].form;

		options = $.extend({
			interval: 20000,
			success: function() {},
			error: function() {},
			send: function() {},
			key: undefined,
			saving: '.autosave_saving',
			method: form.method || 'post',
			url: form.action || window.location.href
		}, options);

		var elems;

		if($(this[0]).is('form'))
			elems = $(':input', this[0]);
		else
			elems = this;

		var values_changed = false;

		elems.change(function() { 
			values_changed = true; 
		});

		function get_values()//{{{
		{
			var values = {};
			elems.each(function() {
				if(!$(this).is(':input') || 
				   ($(this).is(':radio') && !this.checked))
				{
					return;
				}

				values[this.name] = $(this).is(':checkbox') ? this.checked 
														    : $(this).val();
			});
			return values;
		}//}}}

		function call_ajax(action, key, data, callback, msg)//{{{
		{
			var ajax_data = 
			{
				key: window.location.href+(key?'?key='+key:''),
				action: action
			};

			if(data !== undefined)
				ajax_data['data'] = $.toJSON(data);

			$(options.saving).text(msg).show(1000);

			$.ajax({
				url: options.url,
				type: options.method,
				dataType: 'json',
				data: ajax_data,
				success: function(o) {
					if(o.error !== undefined)
						$(options.saving).html(o.error);
					else
					{
						$(options.saving)
							.hide(1000, function() { $(this).html(''); });
					}
					if(callback)
						callback(o);
				},
				error: function(req, status, e) {
					$(options.saving).html(erro_ajax(status, e));
					if(callback)
						callback();
				}
			});
		}//}}}

		function do_remove(key, on_remove)//{{{
		{
			call_ajax('delete', key || options.key, undefined, on_remove,
					  'Removendo informações do salvamento automático...');
		}//}}}
		function do_save(key, on_save)//{{{
		{
			if(values_changed)
			{
				var values = get_values();

				call_ajax('update', key || options.key, values, 
						  function(data) 
						  { 
							  if(on_save)
								  on_save(data); 
							  values_changed = false;
						  },
						  'Salvamento automático...');
			}
		}//}}}
		function do_restore(key, on_restore)//{{{
		{
			call_ajax('get', key || options.key, undefined, function(values) {
				var updated_at;
				if(values.hasOwnProperty('updated_at'))
				{
					var matches;
					if(matches = values.updated_at.match(
						/^(\d{4,4})-(\d{2,2})-(\d{2,2}) (\d{2,2}):(\d{2,2}):(\d{2,2})$/))
					{
						updated_at = new Date(matches[1],matches[2]-1,matches[3],
											 matches[4],matches[5],matches[6]);
					}
				}

				if(values.hasOwnProperty('updated_at') && 
				   (!options.before_restore || 
						options.before_restore(updated_at, values.data)))
				{
					var data = values.data;
					elems.each(function() {
						if(!$(this).is(':input') || !(this.name in data))
						{
							return;
						}

						if($(this).is(':checkbox'))
						{
							if(data[this.name])
								this.checked = 'checked';
							else
								$(this).removeAttr('checked');
						}
						else if($(this).is(':radio') )
						{
							if(this.value==data[this.name])
								this.checked = 'checked';
							else
								$(this).removeAttr('checked');
						}
						else
							$(this).val(data[this.name]);
					});
				}
				if(on_restore)
					on_restore(values.data);

			    values_changed = false;
			},'Atualizando formulário com informações do salvamento automático...');
		}//}}}

		setInterval(function() { do_save(); }, options.interval);

		var ret =
		{
			remove: do_remove,
			restore: do_restore,
			save: do_save,
			set_options: function(opts)
			{
				$.extend(options, tops);
			}
		};

		return ret;
	};//}}}
})(jQuery);

// Sistema de enable/disable de elementos
(function($) {
	function save_value(elem)//{{{
	{
	}//}}}
	function enable_element(elem)//{{{
	{
		if(elem.disabled)
		{
			if($(elem).is('a'))
				$(elem).readonly(false);
			else
				elem.disabled = false;
		}
	}//}}}
	function disable_element(elem)//{{{
	{
		if(!elem.disabled)
		{
			if($(elem).is('a'))
				$(elem).readonly(true);
			else
				elem.disabled = true;
		}
	}//}}}

	$.fn.disable = function(dis, preserve_value){//{{{
		if(dis === undefined)
			dis = true;
		if(preserve_value === undefined)
			preserve_value = true;

		this.each(function(){
			if(dis)
			{
				if($(this).is(':checkbox,:radio'))
				{
					$(this).data('disabled_value',$(this).attr('checked'));
					$(this).removeAttr('checked');
				}
				else
				{
					$(this).data('disabled_value',$(this).val());
					$(this).val('');
				}

				if($(this.form).data('validator'))
				{
					$(this).data('validation_rules',$(this).rules('remove'));
					$(this).valid();
				}
				else
					$(this).removeData('validation_rules');

				disable_element(this);
			}
			else
			{
				enable_element(this);

				if(preserve_value)
				{
					if($(this).is(':checkbox,:radio'))
					{
						if(!$(this).attr('checked'))
							$(this).attr('checked',
										 $(this).data('disabled_value'));
					}
					else
					{
						if($(this).val() == '')
							$(this).val($(this).data('disabled_value'));
					}
				}

				var rules = $(this).data('validation_rules');
				if(rules)
				{
					$(this).rules('add',rules);
					$(this).valid();
				}
			}
		});
		return this;
	}//}}}
	$.fn.enable = function(en, preserve_value){//{{{
		if(en === undefined)
			en = true;
		if(preserve_value === undefined)
			preserve_value = true;

		return this.each(function() { $(this).disable(!en, preserve_value); });
	}//}}}
})(jQuery);

// Sistema de enable/disable inteligente
(function($) {
	var elements = {};
	var uuid = 0;

	function unique_id(elem)//{{{
	{
		var id = $.data(elem, 'unique_id');

		if(!id)
		{
			id = ++uuid;
			$.data(elem, 'unique_id', id);
			elements[id] = elem;
		}
		return id;
	}//}}}
	function elem_from_unique_id(id)//{{{
	{
		if(id in elements)
			return elements[id];
		else
			return undefined;
	}//}}}

	function get_value(elem)//{{{
	{
		if($(elem).is(':radio'))
			return $('input[name='+elem.name+']:checked').val();
		else if($(elem).is(':checkbox'))
			return elem.checked;
		else
			return $(elem).val();
	}//}}}

	var update_state_functions = [];

	$.fn.is_readonly = function()//{{{
	{
		if(!window.com_powelltechs_readonly)
			return false;
		return window.com_powelltechs_readonly._hasReadonly(this);
	}//}}}

	function create_state_changer(defs)//{{{
	{
		var rules = {},
			depends = {};

		function do_enable(dep, enable, parent_id, preserve_value)// {{{
		{
			var dep_id = unique_id(dep);

			var is_enabled = defs.is_enabled.call(dep);

			// Se precisamos habilitar,
			if(enable && !is_enabled)
			{
				var can_be_enabled = true;
				$.each(depends[dep_id], function(parent_id2, criterias) {
					if(parent_id2 == parent_id)
						return true;

					var par = elem_from_unique_id(parent_id2),
						parval = get_value(par);

					for(var i=0; i<criterias.length; ++i)
					{
						if(!criterias[i].test_enable.call(par, parval))
						{
							can_be_enabled = false;
							return false;
						}
					}
				});
				if(can_be_enabled)
				{
					defs.enable.call(dep, preserve_value);
					return true;
				}
				else
					return false;
			}
			// Precisamos desabilitar?
			else if(!enable && is_enabled)
			{
				defs.disable.call(dep, preserve_value);
				return true;
			}
			else
				return false;
		}//}}}

		function parse_args(args)//{{{
		{
			var ret = {elems: [], criteria: {}};

			for(var i=0; i<args.length; ++i)
			{
				if(typeof(args[i]) == 'string')
					$(args[i]).each(function() { ret.elems.push(this); });
				else if (typeof(args[i])=='object' && ('tagName' in args[i]))
					ret.elems.push(args[i]);
				else 
				{
					assert(ret.criteria.test_enable === undefined);
					if(typeof(args[i]) == 'function')
						ret.criteria.test_enable = args[i];
					else
					{
						assert(typeof(args[i]) == 'object');
						assert(args[i].test_enable !== undefined);

						ret.criteria = args[i];
					}
				}
			}

			return ret;
		}//}}}

		function call_criterias(par, dep, parent_id, parval, criterias,//{{{
								on_state_change)
		{
			for(var i=0; i<criterias.length; ++i)
			{
				var enable = criterias[i].test_enable.call(par, parval);

				var oldval = get_value(dep);

				if(do_enable(dep,enable,parent_id,criterias[i].preserve_value))
				{
					if(enable)
					{
						if(criterias[i].on_enable)
							criterias[i].on_enable.call(dep);
					}
					else
					{
						if(criterias[i].on_disable)
							criterias[i].on_disable.call(dep);
					}

					if(on_state_change && oldval != get_value(dep))
						on_state_change(dep);
				}

			}
		}//}}}

		var funs = {};

		funs[defs.name_direct] = function() {//{{{
			var def = parse_args(arguments);

			// Para cada elemento que habilitará/desabilitará outros,
			$(this).each(function() {
				var par = this;
				var parent_id = unique_id(this);

				if(!(parent_id in rules))
					rules[parent_id] = {};		

				function add_dependent(dep, criteria)
				{
					dep_id = unique_id(dep);

					if(!(dep_id in depends))
						depends[dep_id] = {};

					if(!(parent_id in depends[dep_id]))
						depends[dep_id][parent_id] = [];

					depends[dep_id][parent_id].push(criteria);

					if(!(dep_id in rules[parent_id]))
						rules[parent_id][dep_id] = [];

					rules[parent_id][dep_id].push(criteria);
				}

				// Para cada elemento dependente a ser habilitado/desabilitado,
				for(var i=0; i<def.elems.length; ++i)
					add_dependent(def.elems[i], def.criteria);

				// Quando o elemento habilitador for mudado,
				$(this).change(function() {
					var reentrancy_guard = {};
					function do_it(par)
					{
						var parent_id = unique_id(par);

						if(!(parent_id in rules))
							return;

						if(reentrancy_guard[parent_id] >= 1)
							return;

						if(reentrancy_guard[parent_id] === undefined)
							reentrancy_guard[parent_id] = 1;
						else
							++reentrancy_guard[parent_id];

						var parval = get_value(par);

						$.each(rules[parent_id], function(dep_id, criterias) {
							var dep = elem_from_unique_id(dep_id);
							call_criterias(par,dep,parent_id,parval,criterias,
										   do_it);
						});

						--reentrancy_guard[parent_id];
						if(reentrancy_guard[parent_id] == 0)
							delete reentrancy_guard[parent_id];
					}
					do_it(this);
				});
			});
			return this;
		};//}}}
		funs[defs.name_inverse] = function() {//{{{
			var def = parse_args(arguments);

			$(this).each(function() {
				for(var i=0; i<def.elems.length; ++i)
					$(def.elems[i]).enables(this, def.criteria);
			});
			return this;
		}; //}}}

		update_state_functions.push( function() { // {{{
			$.each(depends, function(dep_id, parents) {
				var dep = elem_from_unique_id(dep_id);
				$.each(parents, function(parent_id, criterias) {
					var par = elem_from_unique_id(parent_id);
					var parval = get_value(par);

					call_criterias(par, dep, parent_id, parval, criterias);
				});
			});
			return this;
		});// }}}

		$.extend($.fn, funs);
	};//}}}

	$.update_state = function() 
	{
		for(var i = 0; i<update_state_functions.length; ++i)
			update_state_functions[i]();
	}

	// enables
	create_state_changer({
		name_direct: 'enables',
		name_inverse: 'enabled_by',

		enable: function(preserve_val) { $(this).enable(true,preserve_val); },
		disable: function(preserve_val) { $(this).disable(true,preserve_val); },
		is_enabled: function() { return !this.disabled; }
	});

	// shows
	create_state_changer({
		name_direct: 'shows',
		name_inverse: 'shown_by',

		enable: function() { $(this).show(); },
		disable: function() { $(this).hide(); },
		is_enabled: function() { return $(this).is(':visible'); }
	});

	// makes_writable
	create_state_changer({
		name_direct: 'makes_writable',
		name_inverse: 'made_writable_by',

		enable: function() { $(this).readonly(false); },
		disable: function() { $(this).readonly(true); },
		is_enabled: function() { return !$(this).is_readonly(); }
	});
})(jQuery);

