# -*- encoding: utf-8 -*-

#-------------------------------------------------------------------------------
# Name:        menu
# Purpose:     Classe criadora de menus
#
# Author:      Mateus
#
# Created:     05/07/2011
# Version:     beta 0.2
# Copyright:   (c) Mateus 2011
# Licence:     <your licence>
#-------------------------------------------------------------------------------
#!/usr/bin/env python

#-------------------------------------------------------------------------------
# Importações
#-------------------------------------------------------------------------------
import os # Verificar OS

if os.environ['OS'] == "Windows_NT":
    import msvcrt
    sistOperacional = "Windows_NT"

else:
    sistOperacional = "Linux"

#-------------------------------------------------------------------------------


#-------------------------------------------------------------------------------
# Métodos para futuras classes
#-------------------------------------------------------------------------------
def tipoVariavel(variavel):
    """
    Desc: Retorna o tipo que a 'variavel' é

    variavel = Mixed: Variável que você quer verificar

    return = Str: Tipo de variável
    """
    tipoVar = str(type(variavel))
    tipoVar = tipoVar.split('\'')
    tipoVar = tipoVar[1]

    return tipoVar


def limparTela(sistOperacional):
    """
    Desc: Limpa a tela do prompt

    sistOperacional = Atribute: os.environ['OS']
    """

    if sistOperacional == "Windows_NT":
        os.system("cls")
    else:
        os.system("clear")


#-------------------------------------------------------------------------------
# Classe
#-------------------------------------------------------------------------------

class Menu:

    global sistOperacional

    sisOperacional = sistOperacional
    limparTela = True

    # ----------------------------------------
    def __init__(self, titulo="Título", menuAnterior=None):
        """
        Desc: Método iniciador

        titulo       = Str: Rótulo do título
        menuAnterior = Menu: Menu anterior
        """

        # List menu
        # [acho que é um id que não funciona, titulo, elementos do menu (itens)]
        self.menu = [0, titulo, []]

        # Menu anterior
        self.menuAnterior = menuAnterior


    '''
    def __repr__(self):
        """
        Desc: Retorna: Dados da classe
        """
        ' ''
        self._retorno  = "Menu:\n"
        self._retorno += "Classe criadora de menus\n\n"

        self._retorno += "Itens do menu:\n"
        ' ''
        self._retorno = str(self.menu)

        return self._retorno
    '''

    # ----------------------------------------

    def iniciar(self):
        """
        Desc: Iniciar sistema
        """
        pass


    # ----------------------------------------
    def executar(self):


        # Impressão
        #  Cabeçalho
        self._imprimirCabecalho()

        #  Listando os elementos
        totalItens = self._imprimirItens()

        #  Se o menu não possui opções
        if totalItens == 0:
            print("Este menu não possui opções! \nVoltando ao menu anterior", end="\n\n")
            self.menuAnterior.executar()
            print()
            return

        # Captura de tecla
        print("escolha uma opção: ")
        opcaoSelecionada = self._capturarTecla(totalItens)

        # Chamar função
        self._executarFuncao(opcaoSelecionada)


        '''
        # Limpar a tela
        if self.limparTela == True:
            limparTela(self.sisOperacional)
        '''

        # Quando executar um procedimento em vez de chamar um sub menu,
        # deve-se retornar ao menu do procedimento
        self.executar()



    # ----------------------------------------


    # ----------------------------------------
    #  Métodos de impressão
    # ----------------------------------------

    def _imprimirCabecalho(self, nivel=0, tamBarra=30, caractere="*"):
        """
        Desc: Imprime o cabecalho do menu

        nivel     = Int: Nivel atual do menu
        tamBarra  = Int: Total de caracteres no na perfumaria do menu
        caractere = Str: Perfumaria a ser utilizada.
                         O código pressupõe que o carartere só possua um carácter
        """

        # Cálculos
        varTemp = int((tamBarra - len(self.menu[1])-2)/2)

        if (tamBarra - len(self.menu[1])-2)%2 == 1:
            varTemp2 = varTemp+1
        else:
            varTemp2 = varTemp


        # Cabeçalho
        print(caractere * tamBarra) # Barra
        print(caractere * varTemp,  self.menu[1], caractere * varTemp2) # Titulo do menu
        print(caractere * tamBarra) # Barra
        print()


    def _imprimirItens(self, numInicial=1, caractere="-"):
        """
        Desc: Imprime os elementos itens de 'self'

        numInicial = Int: Número inicial de listagem
        caractere  = Str: Caractere separador

        return = Int: Total de itens dessa lista
        """

        numItens = 0

        for elem in self.menu[2]:

            if tipoVariavel(elem) == "list":
                print(numInicial, caractere, elem[1])
            else:
                print(numInicial, caractere, elem.menu[1])

            numInicial +=1
            numItens +=1

        print()

        return numItens

    # ----------------------------------------


    # ----------------------------------------
    #  Métodos de captura de tecla
    # ----------------------------------------

    def _capturarTecla(self, numFinal, numInicial=0):
        """
        Desc: Captura a tecla que o usuário final tecla para ativar a opção do menu

        numFinal   = Int: Número final de elementos da lista.
                          O máximo que a classe suporta é "9"
        numInicial = Int: Número inicial de contagem

        return = Int: Elemento selecionado dentro das opções possíveis
        """


        #  Método de captura depende do sistema operacional a ser utilizado
        if self.sisOperacional == "Windows_NT":

            opcaoSelecionada = msvcrt.getch()

            #  Convertendo para formato utilizado pelo sistema
            opcaoSelecionada = str(opcaoSelecionada)
            opcaoSelecionada = ord(opcaoSelecionada[2])

            # Verificar se a tecla pressionada é uma opção
            #    not (Tecla selecionada é um número)  (concatenado com) not (Selecionado uma das opções)
            while (opcaoSelecionada <= ord(str(numInicial)) or opcaoSelecionada > ord(str(numFinal))):
                opcaoSelecionada = str(msvcrt.getch())
                opcaoSelecionada = ord(opcaoSelecionada[2])

            # Conversão para string
            opcaoSelecionada = chr(opcaoSelecionada)

        else:
            opcaoSelecionada = input()


        # Conversão para inteiro
        opcaoSelecionada = int(opcaoSelecionada)

        return opcaoSelecionada

    # ----------------------------------------


    # ----------------------------------------
    #  Métodos execução de procedimenos
    # ----------------------------------------
    def _executarFuncao(self, opcaoSelecionada):
        """
        Desc: Ativaa função do item selecionado do menu ('opcaoSelecionada')

        opcaoSelecionada = Int: Ítem do menu selecionado

        return = Int: Elemento selecionado dentro das opções possíveis
        """

        elemSelecionado = self.menu[2][opcaoSelecionada - 1]

        print() # Perfumaria

        # Possuindo uma função para executar
        if tipoVariavel(elemSelecionado) == "list":
            '''
            print()
            print(' (LINHA 273: \nExecutar função de:', elemSelecionado[1]+") ")
            print()
            '''

            # Funções padrões do sistema
            if elemSelecionado[2] == "retornar()":

                if self.limparTela == True:
                    limparTela(self.sisOperacional)

                self.menuAnterior.executar()


            else:
                exec(elemSelecionado[2])

        # É um menu
        else:
            '''
            print()
            print(' (LINHA 279: Sub item:) ')
            print()
            '''

            elemSelecionado.executar()

    # ----------------------------------------


    # ----------------------------------------


    def adicionarSubMenu(self, caminho, rotulo):
        """
        Desc: Adiciona um submenu a um menu

        caminho = List: []: Raiz
        rotulo  = Str: Rótulo do item do menu
        """
        # Se for o menu principal
        if caminho == []:
            self._adicionandoElem(caminho, Menu(rotulo, self))

        # Se for um sub menu qualquer
        else:
            # Achar menu anterior
            varTemp = self.menu[2]
            for pos in caminho:
                varTemp = varTemp[pos]

            # Criando sub menu
            self._adicionandoElem(caminho, Menu(rotulo, varTemp))




    def adicionarItem(self, caminho, rotulo, funcao, *arg):
        """
        Desc: Adicionar item a um menu

        caminho = List: []: Raiz

        rotulo = Str: Rótulo do item do menu
        funcao = Str: Nome da função
        arg    = Argumentos da funcao
        """

        self._adicionandoElem(caminho, [1, rotulo, funcao])


    def _adicionandoElem(self, caminho, elemento):
        """
        Desc: Adicionar elemento a um menu

        caminho = List: []: Raiz
        elemento = Conteudo que será inserido no menu
        """

        if caminho == []:
            self.menu[2].append(elemento)
        else:
            # Classe menu -> self.menu
            # Primeiro []  -> Acesso aos elementos da Lista Menu.menu
            #  [2]          -> PONTEIRO PARA: Itens do menu
            # Segundo []   -> Acesso aos itens do menu
            #  caminho[0]   -> PONTEIRO PARA: SubMenu pedido
            # Classe menu -> [caminho[2]]
            # Método -> _adicionandoElem()

            self._varTemp = caminho.pop(0)

            self.menu[2][self._varTemp]._adicionandoElem(caminho, elemento)



    # ----------------------------------------


    def imprimir(self, menu=None):

        if menu == None:
            menu = self.menu

        for valor in menu:
            print('-', valor)

        print()


    # ----------------------------------------

#-------------------------------------------------------------------------------






#-------------------------------------------------------------------------------
# Execução
#-------------------------------------------------------------------------------
def imprimir(imprimir="Eu que fiz essa função! xD"):

    print(imprimir)

    print()
    input("LINHA 400 (Dentro do procedimento imprimir()): \
           \nDigite Enter para finalizar este procedimento")
    print()



if __name__ == '__main__':

    menu = Menu("Menu Principal")

    menu.adicionarSubMenu([], "Geometria plana")
    menu.adicionarSubMenu([], "Geometria espacial")
    menu.adicionarSubMenu([], "Geometria analítica")
    menu.adicionarSubMenu([], "Sobre")
    menu.adicionarItem([], "Sair", 'quit()')

    # Geomeria plana
    menu.adicionarItem([0], "Lei dos Senos", "imprimir('Testando impressão da opção 1')")
    menu.adicionarItem([0], "Teorema de pitagoras", "imprimir('Testando impressão da opção 2')")
    menu.adicionarSubMenu([0], "SubMenu")
    menu.adicionarItem([0], "Retornar ao menu anterior", "retornar()")

    #  Geometria plana -> SubMenu
    menu.adicionarItem([0, 2], "Item 1", "imprimir()")
    menu.adicionarItem([0, 2], "Item 2", "imprimir()")
    menu.adicionarItem([0, 2], "Item 3", "imprimir()")
    menu.adicionarItem([0, 2], "Retornar ao menu anterior", "retornar()")


    # Geometria espacial
    menu.adicionarItem([1], "Lambda", "imprimir()")
    menu.adicionarItem([1], "Teorema de pitagoras", "imprimir()")
    menu.adicionarItem([1], "Retornar ao menu anterior", 'retornar()')


    # Sobre
    menu.adicionarItem([3], "Autor", "imprimir('Paulo Mateus Moura da Silva')")
    menu.adicionarItem([3], "Data do imprimir do desenvolvimento", "imprimir('05/07/2011')")
    menu.adicionarItem([3], "Versão", "imprimir('Versão beta 0.1')")
    menu.adicionarItem([3], "Retornar ao menu anterior", 'retornar()')

    '''
    menu.imprimir()
    menu.imprimir(menu.menu[2])
    menu.imprimir(menu.menu[2][0].menu)
    menu.imprimir(menu.menu[2][0].menu[2][2].menu)
    '''
    print("LINHA 448: Preciso desenvolver o sistema de bradcrumb!")
    menu.executar()