#############################################################################
#																			#
#				Programa que permite encontrar tu CURP						#
#					Diego Alberto Magallanes Ramirez						#
#																			#
#############################################################################

# Lista de letras con tildes
accents = [
	'\u00C1',	# Á
	'\u00C9',	# É
	'\u00CD',	# Í
	'\u00D3', 	# Ó
	'\u00DA',	# Ú
	'\u00D1'	# Ñ
]

# Lista de letras sin tildes
no_accents = ['A', 'E', 'I', 'O', 'U', 'X']

# Lista de vocales
vocals = ['A', 'E', 'I', 'O', 'U']

# Número de días por mes
days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]

# Lista de estados
states = [
	'AGUASCALIENTES',
	'BAJACALIFORNIA',
	'BAJACALIFORNIASUR',
	'CAMPECHE',
	'CHIAPAS',
	'CHIHUAHUA',
	'CIUDADDEMEXICO',
	'COAHUILA',
	'COLIMA',
	'DURANGO',
	'GUANAJUATO',
	'GUERRERO',
	'HIDALGO',
	'JALISCO',
	'ESTADODEMEXICO',
	'MICHOACAN',
	'MORELOS',
	'NAYARIT',
	'NUEVOLEON',
	'OAXACA',
	'PUEBLA',
	'QUERETARO',
	'QUINTANAROO',
	'SANLUISPOTOSI',
	'SINALOA',
	'SONORA',
	'TABASCO',
	'TAMAULIPAS',
	'TLAXCALA'
	'VERACRUZ',
	'YUCATAN',
	'ZACATECAS'
]

# Lista de códigos de estado
states_code = [
	'AG',
	'BC',
	'BS',
	'CM',
	'CS',
	'CH',
	'DF',
	'CO',
	'CL',
	'DG',
	'GT',
	'GR',
	'HG',
	'JC',
	'ME',
	'MI',
	'MO',
	'NA',
	'NL',
	'OA',
	'PU',
	'QT',
	'QR',
	'SL',
	'SI',
	'SO',
	'TB',
	'TM',
	'TL',
	'VE',
	'YU',
	'ZA'
]

# Función que elimina las tildes de una palabra
def quitaTildes(cadena):
	nueva_cadena = ''
	for letra in cadena:	# Recorre la cadena letra por letra
		if letra in accents:	# Verifica si tiene acentos
			indice = accents.index(letra)	# Obtiene el indice dentro de la lista
			letra = no_accents[indice]	# Cambia la letra con tilde por una sin tilde

		nueva_cadena = nueva_cadena + letra

	return nueva_cadena


# Funcion que da formato a una cadena:
# Elimina espacios
# Todo en mayúsculas
# Elimina tildes
def aplicaFormato(cadena):
	cadena = cadena.replace(' ', '')
	cadena = cadena.upper()
	cadena = quitaTildes(cadena)

	return cadena

# Regresa la primera vocal interna que encuentre.
def vocalInterna(cadena):
	for letra in cadena[1:]:
		if letra in vocals:
			return letra

# 10/06/1995
# [10, 06, 1995]
# Separa la fecha por / y regresa el día, mes y año.
def procesaFecha(fechaFormato):
	fecha = fechaFormato.split('/')
	return fecha[0], fecha[1], fecha[2]

# Obtiene el código del estado correspondiente.
def getEstado(estado):
	indice = states.index(estado)
	return states_code[indice]

# Obtiene la primera consonante interna.
def consonanteInterna(cadena):
	for letra in cadena[1:]:
		if letra not in vocals:
			return letra

# p  = Divisible entre 4.
# ¬q = No divisible entre 100.
# r  = Divisible entre 400. (2000 y 2400 son bisiestos pues aún siendo divisibles entre 100 lo son también entre 400. Pero los años 1900, 2100, 2200 y 2300 no lo son porque sólo son divisibles entre 100).
# p y (¬q o r)
# Decide si un año es bisiesto.
# True - Si es bisiesto.
# False - E.o.c.
def es_bisiesto(año):
	return (año % 4 == 0) and ((not año % 100 == 0) or (año % 400 == 0))

# Decide si una fecha es correcta.
# Verifica si un año es bisiesto, si el día está en el rango correspondiente por mes.
def validaFecha(dia, mes, año):
	if mes == 2:
		if es_bisiesto(año):
			return dia > 0 and dia <= 29
		else:
			return  dia > 0 and dia <= 28

	max_dias = days[mes-1]

	return dia > 0 and dia < max_dias


#################################################
#												#
#		Aquí empieza el programa 				#
#												#	
#################################################

nombre = aplicaFormato(input('Ingresa tu nombre(s): '))
ap_paterno = aplicaFormato(input('Ingresa tu apellido paterno: '))
ap_materno = aplicaFormato(input('Ingresa tu apellido materno: '))

while True:
	dia, mes, anio = procesaFecha(input('Ingresa tu fecha de nacimiento (dd/mm/aaaa): '))

	day = int(dia)
	month = int(mes)
	year = int(anio)

	if validaFecha(day, month, year):
		break

	print('Fecha incorrecta vuelve a intentarlo...')

sexo = aplicaFormato(input('Ingresa tu sexo (H) Hombre y (M) Mujer: '))
estado = aplicaFormato(input('Ingresa tu estado: '))

curp = ''
curp += ap_paterno[0]
curp += vocalInterna(ap_paterno)
curp += ap_materno[0]
curp += nombre[0]
curp += str(anio)[2]
curp += str(anio)[3]
curp += str(mes)
curp += str(dia)
curp += str(sexo)
curp += getEstado(estado)
curp += consonanteInterna(ap_paterno)
curp += consonanteInterna(ap_materno)
curp += consonanteInterna(nombre)
curp += '00'

print('Tu CURP es: ', curp)
