// Dependências: valid.js, valid_num.js, date_funcs.js, str.js, num.js e timeformats.js.
//
// Validação de datas.

// Variáveis.
var LastValidatedDate = null // Última data válida processada por 'isDateFieldValid'.


// Retorna 'true' se o conteúdo de 'wd' for uma data válida. 'optReq' é um campo opcional que indica 
// se o campo é mandatório. Se fôr 'true' e o campo estiver vazio, será apresentada uma mensagem de erro 
// ao utilizador e a função retornará 'false'.
function isDateFieldValid (wds, optReq) {
	return apply (function (wd) {
		var str = trim (wd.value)
		if (!str && optReq) return _vError (wd, KMsgReqField)

		var res = isValidDate (str)
		if (!res [0]) return _vError (wd, KMsgInvDate)

		wd.value = res [1]
		LastValidatedDate = res [2]
		return true
	}, wds)
}

// Verifica se 'str' é uma data válida.
// A função retorna 3 argumentos - o primeiro indica se 'str' é de facto válido, o segundo retorna 'str'
// no formato padrão e o terceiro retorna o objecto 'Date' correspondente.
var _isvd_rx
function isValidDate (str) {
	var res = [false, "", null]
	// Encontrar o caractér separador.
	var rx, sep = "", i
	if (_isvd_rx)
		rx = _isvd_rx
	else {
		rx = _isvd_rx = /\S/
		rx.compile ()
	}
	for (i = 0; i < str.length; ++i) {
		var ch = str.charAt (i)
		if (isNaN (ch)) // Verificar se é um separador.
			if (rx.exec (ch)) { // Se também não for um espaço em branco, encontrá-mos o separador.
				sep = ch
				break
			}
	}
	if (sep == "") return res
	// Extraír as secções da data.
	var secs = str.split (sep), iyear = -1
	if (secs.length != 3) return res
	// Encontrar o ano.
	for (i = 0; i < secs.length; ++i) {
		var n = cvtNum (secs [i])
		if (!(secs [i] = n)) return res
		if (n > 31) {
			iyear = i
			break
		}
	}

	if (iyear < 0) return res
	// Com base na posição do ano na data, determinar o formato da data.
	var imon = -1, iday = -1
	switch (iyear) {
	case 0:	// Formato internacional - aaaa/mm/dd.
		imon = 1
		iday = 2
		break
	case 2:	// Formato europeu - dd/mm/aaaa.
		imon = 1
		iday = 0
		break
	}
	var y = parseInt (secs [iyear]), m = parseInt (secs [imon]), d = parseInt (secs [iday])
	// Validar ano, mês e dia.
	if (y < 1000 || y > 2999 || m < 1 || m > 12 || d < 1 || d > getLastDayOfMonth (y, m)) return res

	res [0] = true
	res [2] = new Date (y, m - 1, d)
	res [1] = getDateStr (res [2])
	return res
}

// Indica se a data separada pelos campos CY, CM e CD é válida.
function isValidDateSep (cy, cm, cd, optReq, optMinY, optMaxY) {
	var a = [[cy, "vy", 0], [cm, "vm", 0], [cd, "vd", 0]]
	a.sort (function (a, b) {	return a [0].sourceIndex - b [0].sourceIndex	})
	// Assegurar que é tudo números.
	var i, y, m, d, n = 0, l = a.length, c
	for (i = 0; i < l; ++i) {
		if (!isIntNumField (c = a [i][0])) break
		a [i][2] = ParsedNum
		ParsedNum == 0 && n++ && (c.value = "")
	}
	// Testar a omissão da data.
	if (n == l) return !optReq || reqField (cy)
	// Validar.
	i >= l && (c = null)
	for (i = 0; i < l; ++i)
		if (!eval (a [i][1] + "(" + a [i][2] + ")")) {
			c = a [i][0]
			break
		}
	// O dia só agora pode ser verificado.
	if (!c && (d < 1 || d > getLastDayOfMonth (y, m))) c = cd
	if (c) return _vError (c, KMsgInvDate)
	// Assegurar que a data está dentro dos parâmetros.
	if (optMinY && (y < optMinY))
		return _vError (cy, "O ano tem de ser igual ou superior a " + optMinY + ".")
	if (optMaxY && (y > optMaxY))
		return _vError (cy, "O ano tem de ser igual ou inferior a " + optMaxY + ".")
	// Verificações (executadas acima).
	function vy (n) {	y = n; return n >= 1000 && n <= 2999	}
	function vm (n) {	m = n; return n > 0 && n <= 12	}
	function vd (n) {	d = n; return true	}

	return true
}

