#! -*- coding:UTF-8 -*-
#!/usr/bin/env python

import curses
import thread
import time
import sys
import threading

#------------------------------------------------------------
# matriz para los pares de colores.
# La función init_pair(n, f, b): establece pares de colores.
# n: par color n, f: color primer plano, b: color segundo plano.
# MUY IMPORTANTE:
# El par 0(f: white, b: black) del sistema no puede ser cambiado.
# Nótece, por tanto, que aquí par_color[0] <f: white y b: black> no es 
# el par 0 del sistema sino un par definido por mí.
#            par color primer plano  color segundo plano
par_color = [[1, curses.COLOR_WHITE, curses.COLOR_BLACK],   # par color 0
             [2, curses.COLOR_CYAN, curses.COLOR_BLACK],    # par color 1
	     [3, curses.COLOR_MAGENTA, curses.COLOR_BLACK], # par color 2
	     [4, curses.COLOR_BLUE, curses.COLOR_BLACK],    # par color 3
             [5, curses.COLOR_YELLOW, curses.COLOR_BLACK],  # par color 4
	     [6, curses.COLOR_GREEN, curses.COLOR_BLACK],   # par color 5
	     [7, curses.COLOR_RED, curses.COLOR_BLACK]]     # par color 6

#------------------------------------------------------------
# inicializamos curses, es decir, se determina el tipo de terminal,
# se envían códigos de conf. al mismo y se crean varias estructuras 
# de datos internas. Si hay éxito, initscr() retorna un objeto ventana
# que repesenta la pantalla.
stdscr = curses.initscr()
stdscr.clear()

# tupla para las coordenadas x e y máximas de nuestra pantalla.
x_e_y = stdscr.getmaxyx()

#------------------------------------------------------------
# lista con las opciones del menú de entrada.
l_menu_entrada = ['menu_entrada',
		  'Opciones:',
		  ' ',
		  '   1) Entrada al sistema.',
		  '   2) Administración.',
		  '   3) Terminar.',
		  ' ',
		  'Escoja una opción:']

#------------------------------------------------------------
# funciones.
#------------------------------------------------------------
# función para activar el eco.
def activar_eco():
    curses.echo()
#------------------------------------------------------------
# función para desactivar el eco.
def desactivar_eco():
    curses.noecho()
#------------------------------------------------------------
# función para limpiar un área de la pantalla.
def limpiar_pantalla(x_si = 2, y_si = 1, alto = x_e_y[0]*67/100 - 3, ancho = x_e_y[1] - 2):
    n = 0
    for n in range(n, alto):
	stdscr.addstr(x_si + n, y_si, ' ' * ancho)
    refrescar_pantalla()
#------------------------------------------------------------
# función para dibujar una ventana.
def ventana(vent, x_si = 0, y_si = 0, x_id = x_e_y[0]*67/100, y_id = x_e_y[1] - 1):
    # esquinas(corners) superiores(upper) izquierda(left) y derecha(right).
    vent.addch(x_si, y_si, curses.ACS_ULCORNER)
    vent.addch(x_si, y_id, curses.ACS_URCORNER)
    # esquinas(corners) inferiores(lower) izquierda(left) y derecha(right).
    vent.addch(x_id, y_si, curses.ACS_LLCORNER)
    vent.addch(x_id, y_id, curses.ACS_LRCORNER)
    # líneas horizontales superior e inferior.
    vent.hline(x_si, y_si + 1, curses.ACS_HLINE, y_id - y_si - 1)
    vent.hline(x_id, y_si + 1, curses.ACS_HLINE, y_id - y_si - 1)
    # líneas verticales izquierda y derecha.
    vent.vline(x_si + 1, y_si, curses.ACS_VLINE, x_id - x_si - 1)
    vent.vline(x_si + 1, y_id, curses.ACS_VLINE, x_id - x_si - 1)
    refrescar_pantalla()
#------------------------------------------------------------
# función para refrescar la pantalla.
def refrescar_pantalla():
    stdscr.refresh()
#------------------------------------------------------------
# función para mostrar una línea de texto en pantalla.
def mostrar_texto(x, y, texto, par_color, n):
    curses.init_pair(par_color[n][0], par_color[n][1], par_color[n][2])
    stdscr.addstr(x, y, texto, curses.color_pair(par_color[n][0]))
    refrescar_pantalla()
#------------------------------------------------------------
# función para mostrar una línea de texto centrado en pantalla.
def mostrar_texto_centrado(x, texto, par_color, n):
    curses.init_pair(par_color[n][0], par_color[n][1], par_color[n][2])
    stdscr.addstr(x, x_e_y[1] / 2 - len(texto) / 2 - 1, texto, curses.color_pair(par_color[n][0]))
    refrescar_pantalla()
#------------------------------------------------------------
# función para terminar el modo texto.
def fin_modo_texto():
    curses.endwin()
#------------------------------------------------------------
# función para terminar el Entrenador.
def terminar():
#    borrar_estadistica()
    x = x_e_y[0]*67/100 / 2
    cadena = 'Hasta pronto...'    
    y = x_e_y[1] / 2 - len(cadena) / 2 - 1
    mostrar_texto(x, y, cadena, par_color, 1)
    refrescar_pantalla()
    fin_modo_texto()
    sys.exit(0)
#------------------------------------------------------------
# función para mostrar los menúes.
def menu(lista):
    global proceso

    # número de elementos de la lista.
    numero_elementos = len(lista) 

    # para centrar el menú en el eje de las y.    
    x = x_e_y[0]*67/100 / 2 - numero_elementos / 2

    # para centrar el menú en el eje de las x.
    # obtenemos una lista con las longitudes de las opciones.
    longitudes = [] # lista con las longitudes de las opciones.
    for m in range(0, numero_elementos):
	longitudes.append(len(lista[m]))
    # obtenemos el valor de la longitud mayor.
    if numero_elementos > 0:
	longitud_mayor = longitudes[0] # supuestamente el primer elemento.
	for longitud in longitudes:
	    if longitud > longitud_mayor:
		longitud_mayor = longitud

    y = x_e_y[1] / 2 - longitud_mayor / 2 - 1

    # mostramos las opciones de los menúes.
    # comenzamos desde el elemento 1 para no representar la marca.
    for n in range(1, numero_elementos):
	mostrar_texto(x + n, y, lista[n], par_color, 1)

    refrescar_pantalla()

    # -1 porque la primera opción es lista[0].
    longitud_ultimo_elemento = longitudes[numero_elementos - 1]

    # activamos el eco para mostrar la opción presionada.
    activar_eco()

    # opción seleccionada.
    # escribir la opción seleccionada una posición más a la derecha(+ 1)
    # después de la última línea del menú.
    opcion = stdscr.getch(x + numero_elementos - 1, y + longitud_ultimo_elemento + 1)

    # desactivamos el eco.
    desactivar_eco()

    # a la lista del menú a representar añado la opción entrada por el usuario.
    # IMPORTANTE: puedo añadir un entero a una lista de cadenas.
    lista.append(opcion)

    if opcion == '1': # ¿Entrar?
	#por desarrollar
        pass

    elif opcion == '2': # ¿Administración?
	#por desarrollar
        pass

    elif opcion == '3': # ¿Terminar?
        # terminamos el proceso de ejecución del reloj.
        proceso.exit()
	limpiar_pantalla()
	terminar()
    else:
        limpiar_pantalla()	    
        menu()
#------------------------------------------------------------
# función para mostrar la hora.
def mostrar_hora():
   # Queremos transformar una cadena de hora del tipo:
   # (2007, 5, 22, 16, 13, 52, 1, 142, 1) 
   # (año, mes, día, hora, min, seg, día de la semana, día juliano, ahorro solar)
   # en otra similar a: 16:13:52
   hora_c = time.localtime()

   meridiano = 'a.m.'
   hora = hora_c[3]
   minuto = hora_c[4]
   segundo = hora_c[5]

   # Presentamos la hora en formato de 12h.
   if hora > 12:
      hora = hora - 12
      meridiano = 'p.m.'

   # Arreglo para que hora, minutos y segundos siempre ocupen dos dígitos.
   if hora < 10:
      hora = '0' + str(hora)

   if minuto < 10:
      minuto = '0' + str(minuto)

   if segundo < 10:
      segundo = '0' + str(segundo)

   hora_actual = '< %s:%s:%s %s >' % (hora, minuto, segundo, meridiano)
   mostrar_texto(x_e_y[0]*67/100, x_e_y[1] - 19, hora_actual, par_color, 2)
#------------------------------------------------------------
# clase Reloj.
class Reloj(threading.Thread):
   def __init__(self):
      threading.Thread.__init__(self)           # Required
#     self.interval = interval
   def run(self):
      while 1:
         hora_c = time.localtime()

         meridiano = 'a.m.'
         hora = hora_c[3]
         minuto = hora_c[4]
         segundo = hora_c[5]

         # Presentamos la hora en formato de 12h.
         if hora > 12:
            hora = hora - 12
            meridiano = 'p.m.'

         # Arreglo para que hora, minutos y segundos siempre ocupen dos dígitos.
         if hora < 10:
            hora = '0' + str(hora)

         if minuto < 10:
            minuto = '0' + str(minuto)

         if segundo < 10:
            segundo = '0' + str(segundo)

         hora_actual = '< %s:%s:%s %s >' % (hora, minuto, segundo, meridiano)
         mostrar_texto(x_e_y[0]*67/100, x_e_y[1] - 19, hora_actual, par_color, 2)

#------------------------------------------------------------
# programa principal.
#------------------------------------------------------------
# generales.

# desactivamos los ecos en pantalla.
desactivar_eco()

# arrancamos el empleo de colores.
curses.start_color()

# dibujamos la ventana superior.
ventana(stdscr)

# dibujamos la ventana inferior.
ventana(stdscr, x_e_y[0]*67/100 + 1, 0, x_e_y[0] - 2, x_e_y[1] - 1)

# arrancamos el hilo a partir de una función para mostrar la hora.
# POR ESTA VÍA EL RELOJ NO CAMINA
#thread.start_new_thread(mostrar_hora,())

# arrancamos el hilo a partir de una clase para mostrar la hora.
# POR ESTA OTRA VÍA EL RELOJ CAMINA PERO EL MENÚ SE MAREA
t = Reloj()
t.start()
# conseguimos el nombre del proceso para matarlo luego al presionar la opción terminar.
proceso = t.getName()

# mostramos nuestro menú
menu(l_menu_entrada)

raw_input()
fin_modo_texto()


