# -*- coding: latin-1 -*-

#==========================================================================================================================================
import os
import codecs

from PySide import QtCore, QtGui

from Constantes import *
from Traducir import tr

import Util

import Partida
import ControlPGN
import Analisis
import MotorInterno
import AperturasStd
import XMoscas

import DGT

import Books

import QT.QTUtil as QTUtil
import QT.Controles as Controles

import QT.QTUtil2 as QTUtil2
import QT.Iconos as Iconos
import QT.PantallaAnalisis as PantallaAnalisis
import QT.PantallaTutor as PantallaTutor
import QT.Pelicula as Pelicula

import QT.FormLayout as FormLayout

#==========================================================================================================================================
class Gestor(  ) :
    def __init__( self, procesador ) :

        self.fen = None

        self.procesador = procesador
        self.pantalla = procesador.pantalla
        self.tablero = procesador.tablero
        self.tablero.mostrarPiezas( True, True )
        self.configuracion = procesador.configuracion

        self.liMoscasActivas = procesador.liMoscasActivas

        self.estado = kFinJuego # Para que siempre esté definido

        self.tipoJuego = None
        self.ayudas = None

        self.resultado = kDesconocido

        self.categoria = None

        self.ml = MotorInterno.MotorInterno()

        self.pantalla.ponGestor( self )

        self.partida = Partida.Partida()

        self.listaAperturasStd = AperturasStd.ListaAperturasStd(self.configuracion,False,False)

        self.teclaPanico = procesador.teclaPanico
        self.siTeclaPanico = False

        self.siJuegaHumano = False

        self.pgn = ControlPGN.ControlPGN( self )

        self.xtutor = procesador.xtutor
        self.xrival = procesador.xrival

        self.teclaPanico = 32

        self.unMomento = self.procesador.unMomento
        self.um = None

        self.xRutinaAccionDef = None

        self.xpelicula = None

        self.pantalla.ponTamNormal()

        self.tablero.exePulsadoNum = self.exePulsadoNum

        self.siRevision = True # controla si hay mostrar el rótulo de revisando

        # Capturas
        self.capturasActivable = False

        #x Control del tutor
        #  así sabemos si ha habido intento de análisis previo (por ejemplo el usuario mientras piensa decide activar el tutor)
        self.siIniAnalizaTutor = False

        # Atajos raton :
        self.atajosRatonActivos = False
        self.atajosRatonDestino = None
        self.atajosRatonOrigen = None

        # DGT
        self.compruebaDGT()

    #--------------------------------------------------------------------------------------------------------------------------------
    def ponFinJuego( self ) :
        if self.estado == kFinJuego :
            self.procesador.inicio()
        else :
            self.estado = kFinJuego
            self.pantalla.ponTitulo()
            self.desactivaTodas()
            liOpciones = self.procesador.liOpcionesInicio[:]
            if self.partida.numJugadas() :
                liOpciones.insert( 3, k_otros )
            else :
                self.quitaCapturas()
            self.pantalla.ponToolBar( liOpciones )
            self.quitaAyudas()
            self.procesador.pararMotores()

#--------------------------------------------------------------------------------------------------------------------------------
    def finGestor( self ) :
        # se llama desde procesador.inicio, antes de borrar el gestor
        self.tablero.atajosRaton = None

    #--------------------------------------------------------------------------------------------------------------------------------
    def atajosRatonReset( self ) :
        self.atajosRatonDestino = None
        self.atajosRatonOrigen = None

    #--------------------------------------------------------------------------------------------------------------------------------
    def atajosRaton( self, a1h8 ) :
        if a1h8 is None :
            self.atajosRatonReset()
            return
        # Que hay en esa casilla :
        # vacía o pieza contraria = destino
        # pieza nuestra = origen
        posicion = self.partida.ultPosicion
        pieza = posicion.casillas.get(a1h8, None)
        if pieza is None :
            self.atajosRatonDestino = a1h8
        elif self.siJugamosConBlancas :
            if pieza.isupper() :
                self.atajosRatonOrigen = a1h8
            else :
                self.atajosRatonDestino = a1h8
        else :
            if pieza.isupper() :
                self.atajosRatonDestino = a1h8
            else :
                self.atajosRatonOrigen = a1h8

        # Si no es posible el movimiento -> y estan los dos -> reset + nuevo intento
        # Miramos todos los movimientos que cumplan

        self.ml.ponFen( posicion.fen() )
        self.ml.calculaEstado()
        li = self.ml.listaMovimientos()

        liC = []
        for mov in li :
            a1 = mov.a1()
            h8 = mov.h8()
            siO = (self.atajosRatonOrigen == a1) if self.atajosRatonOrigen else None
            siD = (self.atajosRatonDestino == h8) if self.atajosRatonDestino else None

            if (siO and siD) or ( (siO is None) and siD ) or ( (siD is None) and siO ) :
                t = (a1, h8)
                if not(t in liC) :
                    liC.append( t )

        if len(liC) != 1 :
            if self.atajosRatonOrigen and self.atajosRatonDestino : # Si los dos otra oportunidad dejando sólo el ultimo
                self.atajosRatonReset()
                self.atajosRaton( a1h8 )
                return
            return

        desde = liC[0][0]
        hasta = liC[0][1]
        self.tablero.muevePiezaTemporal( desde, hasta )
        self.tablero.mensajero( desde, hasta )

    #--------------------------------------------------------------------------------------------------------------------------------
    def movimientosPiezas( self, liMovs, siMovTemporizado = False ) :
        """
        Hace los movimientos de piezas en el tablero
        """
        if siMovTemporizado and self.configuracion.efectosVisuales :

            import time
            ttt = time.clock()
            cpu = self.procesador.cpu
            cpu.reset()
            segundos = None

            # primero los movimientos
            for movim in liMovs :
                if movim[0] == "m" :
                    if segundos is None :
                        desde, hasta = movim[1], movim[2]
                        dc = ord(desde[0])-ord(hasta[0])
                        df = int(desde[1])-int(hasta[1])
                        # Maxima distancia = 9.9 ( 9,89... sqrt(7**2+7**2)) = 4 segundos
                        dist = ( dc**2 + df**2 )**0.5
                        segundos = 4.0*dist/9.9

                    cpu.muevePieza( movim[1], movim[2], siExclusiva = False, segundos = segundos )

            if segundos is None :
                segundos = 1.0

            # segundo los borrados
            for movim in liMovs :
                if movim[0] == "b" :
                    n = cpu.duerme( segundos*0.90 )
                    cpu.borraPieza( movim[1], padre = n )

            # tercero los cambios
            for movim in liMovs :
                if movim[0] == "c" :
                    cpu.cambiaPieza( movim[1], movim[2], siExclusiva = True )

            cpu.runLineal()

        else :
            for movim in liMovs :
                if movim[0] == "b" :
                    self.tablero.borraPieza( movim[1] )
                elif movim[0] == "m" :
                    self.tablero.muevePieza( movim[1], movim[2] )
                elif movim[0] == "c" :
                    self.tablero.cambiaPieza( movim[1], movim[2] )

        # Aprovechamos que esta operacion se hace en cada jugada
        if self.atajosRatonActivos :
            self.atajosRatonReset()

    #--------------------------------------------------------------------------------------------------------------------------------
    def numDatos( self ) :
        return self.pgn.numDatos()

    #--------------------------------------------------------------------------------------------------------------------------------
    def ponVista( self ) :
        if (self.pantalla.siCapturas or self.pantalla.siInformacionPGN or self.liMoscasActivas) :
            if not hasattr( self.pgn, "jugada" ) : # gestor60 por ejemplo
                return
            fila, columna = self.pantalla.pgnPosActual()
            posJugada, jg = self.pgn.jugada( fila, columna.clave )
            if jg :
                dic, siBlancas = jg.posicion.capturas()
            else :
                dic, siBlancas = self.partida.ultPosicion.capturas()

            nomApertura = ""
            if jg and jg.siApertura :
                apertura = self.partida.apertura
                if apertura :
                    nomApertura = tr(apertura.nombre)
            if self.pantalla.siCapturas :
                self.pantalla.ponCapturas( dic, jg, nomApertura )
            if self.pantalla.siInformacionPGN :
                self.pantalla.ponInformacionPGN( jg, nomApertura )

            if self.liMoscasActivas :
                if self.siMiraMoscas() :
                    self.miraMoscas( jg )
                else :
                    self.paraMoscas( )

    #--------------------------------------------------------------------------------------------------------------------------------
    def siMiraMoscas( self ) :
        return (self.estado == kFinJuego) or \
                self.tipoJuego in ( kJugEntPos, kJugPGN, kJugEntMaq, kJugGM, kJugSolo, kJugBooks, kJugAperturas )

    #--------------------------------------------------------------------------------------------------------------------------------
    def miraMoscas( self, jg ) :
        fen = jg.posicion.fen() if jg else self.partida.ultPosicion.fen()
        liApagadas = []
        for n, xmosca in enumerate(self.liMoscasActivas) :
            if xmosca.siActiva() :
                xmosca.ponFen( fen )
            else :
                liApagadas.append(n)
        if liApagadas :
            for x in range(len(liApagadas)-1, -1, -1) :
                mosca = self.liMoscasActivas[x]
                mosca.close()
                del self.liMoscasActivas[x]

    #--------------------------------------------------------------------------------------------------------------------------------
    def paraMoscas( self ) :
        for n, xmosca in enumerate(self.liMoscasActivas) :
            xmosca.ponFen( None )

    #--------------------------------------------------------------------------------------------------------------------------------
    def ponPiezasAbajo( self, siBlancas ) :
        self.tablero.ponerPiezasAbajo( siBlancas )
    #--------------------------------------------------------------------------------------------------------------------------------
    def quitaAyudas( self, siTambienTutorAtras=True, siQuitarAtras = True ) :
        self.pantalla.quitaAyudas(siTambienTutorAtras, siQuitarAtras )
        self.siTutorActivado = False
        self.ponActivarTutor(False)
    #--------------------------------------------------------------------------------------------------------------------------------
    def ponAyudas( self, ayudas, siQuitarAtras = True ) :
        self.pantalla.ponAyudas(ayudas, siQuitarAtras)
    #--------------------------------------------------------------------------------------------------------------------------------
    def pensando( self, siPensando ) :
        if siPensando :
            if self.um :
                self.um.final()
            self.um = self.unMomento()
        else :
            if self.um :
                self.um.final()
                self.um = None

    #-----------------------------------------------------------------------------------
    def ponActivarTutor( self, siActivar ) :
        self.pantalla.ponActivarTutor( siActivar )
        self.siTutorActivado = siActivar
    #-----------------------------------------------------------------------------------
    def cambiaActivarTutor( self ) :
        self.siTutorActivado = not self.siTutorActivado
        self.ponActivarTutor( self.siTutorActivado )
    #--------------------------------------------------------------------------------------------------------------------------------
    def desactivaTodas( self ) :
        self.tablero.desactivaTodas( )
    #--------------------------------------------------------------------------------------------------------------------------------
    def activaColor( self, siBlancas ) :
        self.tablero.activaColor( siBlancas )

    #--------------------------------------------------------------------------------------------------------------------------------
    def mostrarIndicador( self, siPoner ) :
        self.tablero.indicadorSC.setVisible( siPoner )
    #--------------------------------------------------------------------------------------------------------------------------------
    def ponIndicador( self, siBlancas ) :
        self.tablero.ponIndicador( siBlancas )
    #--------------------------------------------------------------------------------------------------------------------------------
    def ponMensajero( self, funcMensajero ) :
        self.atajosRatonActivos = self.configuracion.siAtajosRaton

        atajos =self.atajosRaton if self.atajosRatonActivos else None
        self.tablero.ponMensajero( funcMensajero, atajos )

    #--------------------------------------------------------------------------------------------------------------------------------
    def ponFlechaSC( self, desde, hasta ) :
        self.tablero.ponFlechaSC( desde, hasta )
    #--------------------------------------------------------------------------------------------------------------------------------
    def peonCoronado( self, siBlancas ) :
        self.tablero.peonCoronando(siBlancas)
    #--------------------------------------------------------------------------------------------------------------------------------
    def reponPieza( self, posic ) :
        self.tablero.reponPieza( posic )
    #--------------------------------------------------------------------------------------------------------------------------------
    def ponRotulo1( self, mensaje ) :
        self.pantalla.ponRotulo1( mensaje )
    #--------------------------------------------------------------------------------------------------------------------------------
    def ponRotulo2( self, mensaje ) :
        self.pantalla.ponRotulo2( mensaje )
    #--------------------------------------------------------------------------------------------------------------------------------
    def ponRevision( self, siPoner ) :
        if not self.siRevision :
            siPoner = False
        self.pantalla.ponRevision( siPoner )
    #--------------------------------------------------------------------------------------------------------------------------------
    def beep( self ) :
        if self.configuracion.siSuenaBeep :
            QTUtil.beep()

    #--------------------------------------------------------------------------------------------------------------------------------
    def beepExtendido( self ) :
        if self.configuracion.siSuenaJugada :
            jg = self.partida.liJugadas[-1]
            self.procesador.playLista( jg.listaSonidos() )
        elif self.configuracion.siSuenaBeep :
            self.procesador.playBeep(  )

    #--------------------------------------------------------------------------------------------------------------------------------
    def beepResultado( self, resfinal ) :
        if not self.configuracion.siSuenaResultados :
            return
        dic = {
                kGanamos:"GANAMOS",
                kGanaRival:"GANARIVAL",
                kTablas:"TABLAS",
                kTablasRepeticion:"TABLASREPETICION",
                kTablas50:"TABLAS50",
                kTablasFaltaMaterial:"TABLASFALTAMATERIAL",
                kGanamosTiempo:"GANAMOSTIEMPO",
                kGanaRivalTiempo:"GANARIVALTIEMPO"
            }
        if resfinal in dic :
            self.procesador.playClave( dic[resfinal] )

    #--------------------------------------------------------------------------------------------------------------------------------
    def pgnRefresh( self, siBlancas ) :
        self.pantalla.pgnRefresh(siBlancas)
    #--------------------------------------------------------------------------------------------------------------------------------
    def refresh( self ) :
        self.tablero.escena.update()
        self.pantalla.update()
        QTUtil.refreshGUI()

    #--------------------------------------------------------------------------------------------------------------------------------
    def mueveJugada( self, tipo ) :
        partida = self.partida
        fila, columna = self.pantalla.pgnPosActual()
        siBlancas = columna.clave != "NEGRAS"
        siEmpiezaConNegras = partida.siEmpiezaConNegras
        siEmpiezaConBlancas = not siEmpiezaConNegras

        lj = partida.numJugadas()
        if siEmpiezaConNegras :
            lj += 1
        ultFila = (lj-1)/2
        siUltBlancas = lj%2 == 1

        if tipo == "-" :
            if siBlancas :
                fila -= 1
            siBlancas = not siBlancas
            pos = fila*2
            if not siBlancas :
                pos += 1
        elif tipo == "+" :
            if not siBlancas :
                fila += 1
            siBlancas = not siBlancas
        elif tipo == "p" :
            fila = 0
            siBlancas = siEmpiezaConBlancas
        elif tipo == "f" :
            fila = ultFila
            siBlancas = not partida.ultPosicion.siBlancas

        if fila == ultFila :
            if siUltBlancas and not siBlancas :
                return

        if fila < 0 or fila > ultFila :
            self.refresh()
            return
        if fila == 0 and siBlancas and siEmpiezaConNegras :
            siBlancas = False

        self.pantalla.pgnColocate( fila, siBlancas )
        self.pgnMueve( fila, siBlancas )

    #--------------------------------------------------------------------------------------------------------------------------------
    def pgnMueve( self, fila, siBlancas ) :
        self.pgn.mueve( fila, siBlancas )
        self.ponVista()

    #--------------------------------------------------------------------------------------------------------------------------------
    def ponteAlFinal( self ) :
        if self.partida.numJugadas() :
            self.mueveJugada( "f" )
        else :
            self.ponPosicion( self.partida.iniPosicion )
            self.pantalla.base.pgnRefresh() # No se puede usar pgnRefresh, ya que se usa con gobottom en otros lados y aquí eso no funciona
        self.ponVista()

    #--------------------------------------------------------------------------------------------------------------------------------
    def jugadaActual( self ) :
        partida = self.partida
        fila, columna = self.pantalla.pgnPosActual()
        siBlancas = columna.clave != "NEGRAS"
        siEmpiezaConNegras = partida.siEmpiezaConNegras

        numJugadas = partida.numJugadas()
        nj = fila*2
        if not siBlancas :
            nj += 1
        if siEmpiezaConNegras :
            nj -= 1
        return numJugadas, nj, fila, siBlancas

    #--------------------------------------------------------------------------------------------------------------------------------
    def pgnInformacion( self, fila, clave ) :
        self.pantalla.activaInformacionPGN()
        self.ponVista()

    #--------------------------------------------------------------------------------------------------------------------------------
    def vista( self ) :
        menu = Controles.LMenu(puntos=10)

        menu.opcion( "pgn", tr( "TB_INFORMACION_PGN" ), Iconos.TB_InformacionPGNUno() )
        menu.separador()
        menu.opcion( "capturas", tr( "TB_CAPTURAS" ), Iconos.TB_Capturas() )

        resp = menu.lanza()
        if resp == "pgn" :
            self.pantalla.activaInformacionPGN()
        elif resp == "capturas" :
            self.pantalla.activaCapturas()
        self.ponVista()

    #--------------------------------------------------------------------------------------------------------------------------------
    def guardarPGN( self ) :
        conf = self.configuracion

        if conf.salvarFichero :

            try :
                f = codecs.open(conf.salvarFichero,"ab",'utf-8')
                f.write( self.pgn.actual() + "\n\n")
                f.close()
            except :
                QTUtil.ponPortapapeles( self.pgn.actual() )
                QTUtil2.mensError( self.pantalla, "%s : %s\n\n%s"%( tr("IMPOSIBLE_GRABAR"),conf.salvarFichero, tr("GUARDADO_PORTAPAPELES") )  )

    #--------------------------------------------------------------------------------------------------------------------------------
    def guardarGanados( self, siGanado ) :

        conf = self.configuracion

        if siGanado :
            siSalvar = conf.salvarGanados
        else :
            siSalvar = conf.salvarPerdidos

        if siSalvar :
            self.guardarPGN()

    #--------------------------------------------------------------------------------------------------------------------------------
    def guardarNoTerminados( self ) :
        if self.partida.numJugadas() < 2 :
            return

        conf = self.configuracion

        if conf.salvarAbandonados :
            if not QTUtil2.pregunta( self.pantalla, tr( "PREGUNTA_GUARDAR_ABANDONADO" ) ) :
                return
            self.guardarPGN()

    #--------------------------------------------------------------------------------------------------------------------------------
    def capturas( self ) :
        if self.capturasActivable :
            self.pantalla.activaCapturas()
            self.ponVista()
    #--------------------------------------------------------------------------------------------------------------------------------
    def quitaCapturas( self ) :
        self.pantalla.activaCapturas(False)
        self.ponVista()
    #--------------------------------------------------------------------------------------------------------------------------------
    def ponCapturasPorDefecto( self ) :
        self.capturasActivable = True
        if self.configuracion.siActivarCapturas :
            self.pantalla.activaCapturas(True)
            self.ponVista()

    #-----------------------------------------------------------------------------------
    def listado( self, tipo ) :
        if tipo == "pgn" :
            return self.pgn.actual()
        elif tipo == "fen" :
            return self.fenActivo()
        elif tipo == "fns" :
            return self.partida.fensActual()

    #-----------------------------------------------------------------------------------
    def jugadaActiva( self ) :
        fila, columna = self.pantalla.pgnPosActual()
        siBlancas = columna.clave != "NEGRAS"
        pos = fila*2
        if not siBlancas :
            pos += 1
        if self.partida.siEmpiezaConNegras :
            pos = pos - 1
        tam_lj = self.partida.numJugadas()
        siUltimo = (pos+1) >= tam_lj
        if siUltimo :
            pos = tam_lj-1
        return pos, self.partida.liJugadas[pos] if tam_lj else None

    #-----------------------------------------------------------------------------------
    def fenActivo( self ) :
        pos, jg = self.jugadaActiva()
        return jg.posicion.fen() if jg else self.partida.fenActual()

    #-----------------------------------------------------------------------------------
    def fenPrevio( self ) :
        fila, columna = self.pantalla.pgnPosActual()
        siBlancas = columna.clave != "NEGRAS"
        pos = fila*2
        if not siBlancas :
            pos += 1
        if self.partida.siEmpiezaConNegras :
            pos = pos - 1
        tam_lj = self.partida.numJugadas()
        if 0 <= pos < tam_lj :
            return self.partida.liJugadas[pos].posicionBase.fen()
        else :
            return self.partida.iniPosicion.fen()

    #--------------------------------------------------------------------------------------------------------------------------------
    def otros( self, liMasOpciones = None, siCambioTutor = False, siSonidos = False ) :

        menu = Controles.LMenu(puntos=10)

        # Vista
        menuVista = menu.submenu( tr( "TB_VISTA" ), Iconos.TB_Vista() )
        menuVista.opcion( "vista_pgn", tr( "TB_INFORMACION_PGN" ), Iconos.TB_InformacionPGNUno() )
        menuVista.separador()
        menuVista.opcion( "vista_capturas", tr( "TB_CAPTURAS" ), Iconos.TB_Capturas() )
        menu.separador()

        # Grabar
        icoGrabar = Iconos.TB_Grabar()
        icoFichero = Iconos.GrabarFichero()
        icoPortapapeles = Iconos.GrabarPortapapeles()
        icoAzul = Iconos.PuntoAzul()
        icoTras = Iconos.Trastero()
        icoNegro = Iconos.PuntoNegro()
        icoVerde = Iconos.PuntoVerde()
        icoNaranja = Iconos.PuntoNaranja()

        trFichero = tr( "GRABAR_FICHERO" )
        trPortapapeles = tr( "COPIAR_PORTAPAPELES" )

        menuGR = menu.submenu( tr( "TB_GUARDAR" ), icoGrabar )

        menuPGN = menuGR.submenu( tr( "FORMATO_PGN" ), icoAzul )
        menuPGN.opcion( "pgnfichero", trFichero, icoFichero )
        menuPGN.opcion( "pgnportapapeles", trPortapapeles, icoPortapapeles )

        menuGR.separador()

        menuFEN = menuGR.submenu( tr( "FORMATO_FEN" ), icoAzul )
        menuFEN.opcion( "fenfichero", trFichero, icoFichero )
        menuFEN.opcion( "fenportapapeles", trPortapapeles, icoPortapapeles )

        menuGR.separador()

        menuFNS = menuGR.submenu( tr( "LISTA_FENS" ), icoAzul )
        menuFNS.opcion( "fnsfichero", trFichero, icoFichero )
        menuFNS.opcion( "fnsportapapeles", trPortapapeles, icoPortapapeles )

        menuGR.separador()

        menuV = menuGR.submenu( tr( "TABLERO2IMG" ), icoAzul )
        menuV.opcion( "volfichero", trFichero, icoFichero )
        menuV.opcion( "volportapapeles", trPortapapeles, icoPortapapeles )

        menuGR.separador()

        liTras = self.configuracion.liTrasteros
        menuTras = menuGR.submenu( tr( "TRASTEROS" ), Iconos.Trasteros() )
        for ntras, uno in enumerate(liTras) :
            carpeta, trastero = uno
            menuTras.opcion( "trastero_%d"%ntras, "%s  (%s)"%(trastero,carpeta), icoTras )
        menuTras.separador()
        menuTras.opcion( "trastero_nuevo", tr("TRASTERO_NUEVO"), Iconos.Trastero_Nuevo() )
        if liTras :
            icoQuitar = Iconos.Trastero_Quitar()
            menuTrasQ = menuTras.submenu( tr("TRASTERO_QUITAR"), icoQuitar )
            for ntras, uno in enumerate(liTras) :
                carpeta, trastero = uno
                menuTrasQ.opcion( "trastero_quitar_%d"%ntras, "%s  (%s)"%(trastero,carpeta), icoQuitar )

        menu.separador()

        # DGT
        if self.configuracion.siDGT :
            menu.opcion( "dgt", tr( "DESACTIVAR_QUE" if DGT.siON() else "ACTIVAR_QUE", tr("DGT")), Iconos.DGT() )
            menu.separador()

        # Analizar
        if not ( self.tipoJuego == kJugElo and self.estado == kJugando ) :
            menu.opcion( "analizar", tr( "TB_ANALIZAR" ), Iconos.TB_Analizar() )
            menu.separador()

        # Película
        menu.opcion( "pelicula", tr( "PELICULA" ), Iconos.Pelicula() )

        menu.separador()

        # Ciega - Mostrar todas - Ocultar blancas - Ocultar negras
        menuCG = menu.submenu( tr( "CIEGAS" ), Iconos.Ojo() )

        menuCGH = menuCG.submenu( tr( "CIEGAS_OCULTAR" ), icoNegro )
        menuCGH.opcion( "cghbnp", tr( "CIEGAS_TODO"), icoNegro )
        menuCGH.separador()
        menuCGH.opcion( "cghb", tr( "PGN_WHITE"), icoNegro )
        menuCGH.opcion( "cghn", tr( "PGN_BLACK"), icoNegro )
        menuCGH.opcion( "cghp", tr( "CIEGAS_PGN"), icoNegro )
        menuCG.separador()
        menuCGS = menuCG.submenu( tr( "CIEGAS_MOSTRAR" ), icoVerde )
        menuCGS.opcion( "cgsbnp", tr( "CIEGAS_TODO"), icoVerde )
        menuCGS.separador()
        menuCGS.opcion( "cgsb", tr( "PGN_WHITE"), icoVerde )
        menuCGS.opcion( "cgsn", tr( "PGN_BLACK"), icoVerde )
        menuCGS.opcion( "cgsp", tr( "CIEGAS_PGN"), icoVerde )

        # Sonidos
        if siSonidos :
            menu.separador()
            menuSonido = menu.submenu( tr( "TB_SONIDOS" ), Iconos.TB_S_Play() )

            def ico_tit( si ) :
                return (icoNegro, tr( "SONIDOS_DESACTIVAR" )) if si else (icoVerde, tr( "SONIDOS_ACTIVAR" ))

            ico, tit =ico_tit( self.configuracion.siSuenaBeep )
            menuSonido.opcion( "sonido_beep", tit + " " + tr( "SONIDO" ), ico )

            menuSonido.separador()

            ico, tit =ico_tit( self.configuracion.siSuenaResultados )
            menuSonido.opcion( "sonido_resultado", tit + " " + tr( "SONIDOS_RESULTADO" ), ico )

            menuSonido.separador()

            ico, tit =ico_tit( self.configuracion.siSuenaJugada )
            menuSonido.opcion( "sonido_jugada", tit + " " + tr( "SONIDOS_PGN" ), ico )

        # Cambio de tutor
        if siCambioTutor :
            menu.separador()
            menu.opcion( "tutor", tr( "CAMBIO_TUTOR" ), Iconos.Tutor() )

        # Moscas
        if self.siMiraMoscas() :
            menu.separador()
            menuMoscas = menu.submenu( tr( "TB_MOSCAS" ), Iconos.Mosca() )

            liMoscas = XMoscas.listaMoscasRecuperar(self.configuracion)
            dico = { "S":icoVerde, "C": icoAzul, "J":icoNaranja }
            for nmosca, mosca in enumerate(liMoscas) :
                menuMoscas.opcion( "mosca_%d"%nmosca, mosca["NOMBRE"], dico[mosca["TIPO"]] )

            menuMoscas.separador()
            menuMoscas.opcion( "mosca_nueva", tr("NUEVO"), Iconos.TB_Nuevo() )
            if liMoscas :
                menuMoscas.separador()
                menuMoscasBorrar= menuMoscas.submenu( tr("BORRAR"), Iconos.TB_Borrar() )
                for nmosca, mosca in enumerate(liMoscas) :
                    menuMoscasBorrar.opcion( "mosca_quitar_%d"%nmosca, mosca["NOMBRE"], icoNegro )

        # Mas Opciones
        if liMasOpciones :
            menu.separador()
            for clave, rotulo, icono in liMasOpciones :
                if rotulo == None :
                    menu.separador()
                else :
                    menu.opcion( clave, rotulo, icono )

        resp = menu.lanza()
        if resp :

            if liMasOpciones :
                for clave, rotulo, icono in liMasOpciones :
                    if resp == clave :
                        return resp

            if resp == "analizar" :
                self.analizar( )
            elif resp == "dgt" :
                DGT.cambiarON_OFF()
                self.compruebaDGT()

            elif resp == "pelicula" :
                self.pelicula()
            elif resp.startswith( "trastero" ) :
                self.trasteros(resp[9:])

            elif resp.startswith( "vista_" ) :
                if resp.endswith( "pgn" ) :
                    self.pantalla.activaInformacionPGN()
                else :
                    self.pantalla.activaCapturas()
                self.ponVista()

            elif resp.startswith( "mosca_" ) :
                self.moscas( liMoscas, resp[6:] )

            elif resp.startswith( "sonido_" ) :
                if resp.endswith( "jugada" ) :
                    self.configuracion.siSuenaJugada = not self.configuracion.siSuenaJugada
                elif resp.endswith( "resultado" ) :
                    self.configuracion.siSuenaResultados = not self.configuracion.siSuenaResultados
                elif resp.endswith( "beep" ) :
                    self.configuracion.siSuenaBeep = not self.configuracion.siSuenaBeep
                self.configuracion.graba()

            elif resp == "tutor" :
                self.cambioTutor()

            #---------------------------------------------------------------------
            elif resp.startswith( "vol" ) :
                accion = resp[3:]
                if accion == "fichero" :
                    extension = "png"
                    resp = QTUtil2.salvaFichero( self.pantalla, tr( "INDICA_FICHERO" ), self.configuracion.dirSalvados, tr("FICHERO")+" PNG (*.png)", False )
                    if resp :
                        self.tablero.salvaEnImagen( resp, "png" )

                else :
                    self.tablero.salvaEnImagen( )

            #---------------------------------------------------------------------
            elif resp.startswith( "cg" ) :
                orden = resp[2:]
                siMostrar = orden[0] == "s"
                que = orden[1:]
                if "p" in que :
                    self.pgn.siMostrar = siMostrar
                    self.pantalla.base.pgnRefresh()

                b = siMostrar if "b" in que else None
                n = siMostrar if "n" in que else None
                if ("b" in que ) or ( "n" in que ) :
                    self.tablero.mostrarPiezas( b, n )

            #---------------------------------------------------------------------
            else :
                extension = resp[:3]
                siFichero = resp.endswith( "fichero" )
                dato = self.listado( extension )
                if siFichero :
                    resp = QTUtil2.salvaFichero( self.pantalla, tr( "INDICA_FICHERO" ), self.configuracion.dirSalvados, tr("FICHERO")+" %s (*.%s)"%(extension,extension), False )
                    if resp :
                        try :

                            modo = "wb"
                            if Util.existeFichero( resp ) :
                                yn = QTUtil2.preguntaCancelar( self.pantalla, tr( "FICHERO_EXISTE", resp ), si=tr("AÑADIR"), no=tr("SOBREESCRIBIR") )
                                if yn is None :
                                    return
                                if yn :
                                    modo = "ab"
                                    dato = "\r\n"*2 + dato
                            f = codecs.open(resp,modo,'utf-8')
                            f.write( dato )
                            f.close()
                            QTUtil2.mensaje( self.pantalla, "%s"%tr("GRABADO",resp ) )
                            direc = os.path.dirname( resp )
                            if direc != self.configuracion.dirSalvados :
                                self.configuracion.dirSalvados = direc
                                self.configuracion.graba()
                        except :
                            QTUtil.ponPortapapeles( dato )
                            QTUtil2.mensError( self.pantalla, "%s : %s\n\n%s"%( tr("IMPOSIBLE_GRABAR"),resp, tr("GUARDADO_PORTAPAPELES") ) )

                else :
                    QTUtil.ponPortapapeles( dato )
        return None

    #--------------------------------------------------------------------------------------------------------------------------------
    def analizaTutor( self ) :
        self.pensando(True)
        fen = self.partida.ultPosicion.fen()
        if not self.siTerminada() :
            self.mrmTutor = self.xtutor.analiza( fen )
        self.pensando(False)

    #--------------------------------------------------------------------------------------------------------------------------------
    def cambioTutor( self ) :
        resp = PantallaTutor.cambioTutor( self.pantalla, self.configuracion )
        if resp :
            claveMotor, tiempo, difpts, difporc = resp
            tutor = self.configuracion.buscaTutor( claveMotor )
            self.xtutor = self.procesador.creaTutor( tutor, tiempo, None )
            self.ponRotulo2( tr( "TUTOR" ) + ": <b>" + self.xtutor.nombre )
            self.siAnalizadoTutor = False
            self.configuracion.tutor = tutor
            self.configuracion.tiempoTutor = tiempo
            self.configuracion.tutorDifPts = difpts
            self.configuracion.tutorDifPorc = difporc

            self.configuracion.graba()

    #--------------------------------------------------------------------------------------------------------------------------------
    def siTerminada( self ) :
        fen = self.partida.ultPosicion.fen()
        self.ml.ponFen( fen )
        return self.ml.siTerminada()

    #-----------------------------------------------------------------------------------
    def dameJugadaEn( self, fila, clave ) :
        siBlancas = clave != "NEGRAS"

        pos = fila*2
        if not siBlancas :
            pos += 1
        if self.partida.siEmpiezaConNegras :
            pos -= 1
        tam_lj = self.partida.numJugadas()
        if tam_lj == 0 :
            return
        siUltimo = (pos+1) >= tam_lj

        jg = self.partida.liJugadas[ pos ]
        return jg, siBlancas, siUltimo, tam_lj, pos

    #-----------------------------------------------------------------------------------
    def analizaPosicion( self, fila, clave ) :

        jg, siBlancas, siUltimo, tam_lj, pos = self.dameJugadaEn( fila, clave )
        if jg.siJaqueMate :
            return

        if (self.estado != kFinJuego) and (self.tipoJuego not in [kJugEntPos, kJugPGN, kJugEntMaq, kJugGM, kJugSolo, kJugBooks, kJugAperturas]) : #%#
            if siUltimo or self.ayudas == 0 :
                return
            maxRecursion = tam_lj-pos-3 #%#
        else :
            maxRecursion = 9999
        Analisis.MuestraAnalisis( self.procesador, self.xtutor, jg, siBlancas, maxRecursion, pos )
        self.ponVista()

    #-----------------------------------------------------------------------------------
    def analizar( self ) :

        param = PantallaAnalisis.paramAnalisis( self.pantalla, self.procesador.configuracion, True )

        if param is None :
            return

        claveMotor, tiempo, blancas, negras, jugadas, siBorrarPrevios = param

        siTutor = claveMotor == self.xtutor.clave
        if  siTutor :
            xgestor = self.xtutor
        else :
            confMotor = self.procesador.configuracion.buscaMotor( claveMotor )
            xgestor = self.procesador.creaGestorMotor( None, confMotor, tiempo, None, True )

        liJugadas = []

        lni = Util.ListaNumerosImpresion(jugadas)
        numJugada = int(self.partida.primeraJugada())
        siBlancas = not self.partida.siEmpiezaConNegras
        for nRaw in range(self.partida.numJugadas()) :
            siGrabar = lni.siEsta( numJugada )
            if siGrabar :
                if siBlancas :
                    if not blancas :
                        siGrabar = False
                elif not negras :
                    siGrabar = False
            if siGrabar :
                liJugadas.append(nRaw)
            siBlancas = not siBlancas
            if siBlancas :
                numJugada += 1

        numJugadas = len(liJugadas)
        mensaje = tr("ANALIZANDO")
        tmpBP = QTUtil2.BarraProgreso( self.pantalla, tr("ANALISIS" ), mensaje, numJugadas ).mostrarAD()

        for n,nRaw in enumerate(liJugadas) :
            jg = self.partida.liJugadas[nRaw]

            if jg.analisis and not siBorrarPrevios :
                continue

            if tmpBP.siCancelado() :
                break

            tmpBP.mensaje( mensaje + " %d/%d"%( n+1,numJugadas) )
            tmpBP.pon( n )
            if not (jg.siJaqueMate or jg.siTablas() ):
                jg.analisis = xgestor.analizaJugada( jg, tiempo )
            self.ponPosicion( jg.posicion )
            self.pantalla.pgnColocate( nRaw/2, (nRaw+1)%2 )

        tmpBP.cerrar()

        if not siTutor :
            xgestor.terminar()

        if self.estado == kJugando and self.siJuegaHumano and self.partida.numJugadas():
            jg = self.partida.liJugadas[-1]
            self.tablero.ponFlechaSC( jg.desde, jg.hasta )
            self.activaColor( self.partida.ultPosicion.siBlancas )

    #-----------------------------------------------------------------------------------
    def cambiaRival( self, nuevo ) :
        self.procesador.cambiaRival( nuevo )

    #-----------------------------------------------------------------------------------
    def pelicula( self ) :
        resp = Pelicula.paramPelicula( self.pantalla )
        if resp is None :
            return

        segundos, siInicio = resp

        self.xpelicula = Pelicula.Pelicula( self, segundos, siInicio )

    #-----------------------------------------------------------------------------------
    def ponRutinaAccionDef( self, rutina ) :
        self.xRutinaAccionDef = rutina

    #-----------------------------------------------------------------------------------
    def rutinaAccionDef( self, clave ) :
        if self.xRutinaAccionDef :
            self.xRutinaAccionDef( clave )

    #-----------------------------------------------------------------------------------
    def finalX0( self ) :
        # Se llama desde la pantalla al pulsar X
        # Se comprueba si estamos en la película
        if self.xpelicula :
            self.xpelicula.terminar()
            return False
        return self.finalX()

    #--------------------------------------------------------------------------------------------------------------------------------
    def ponFlechas( self, fen, siMB, siMovimientos, si2 ) :
        self.ml.ponFen( fen )
        self.ml.calculaEstado()
        if si2 :
            li = self.ml.listaCapturas2( siMB, siMovimientos )
        else :
            if siMovimientos :
                li = self.ml.listaMovimientos() if siMB else self.ml.listaMovimientosOB()
            else :
                li = self.ml.listaCapturas( siMB )

        for m in li :
            if si2 :
                m1,m2 = m
                pv = m1.pv()
                d = pv[:2]
                h = pv[2:4]
                self.tablero.creaFlechaMov( d, h, "bm" if siMovimientos else "b"  )
                pv = m2.pv()
                d = pv[:2]
                h = pv[2:4]
                self.tablero.creaFlechaMov( d, h, "m" if siMovimientos else "c"  )
            else :
                pv = m.pv()
                d = pv[:2]
                h = pv[2:4]
                self.tablero.creaFlechaMov( d, h, "m" if siMovimientos else "c"  )

    #--------------------------------------------------------------------------------------------------------------------------------
    def exePulsadoNum( self, siIzq, siActivar, numero  ) :
        if numero in [1,2,7,8] :
            if siActivar :
                # Que jugada está en el tablero
                fila, columna = self.pantalla.pgnPosActual()
                if fila == -1 :
                    fen = self.partida.iniPosicion.fen()
                else :
                    jg, siBlancas, siUltimo, tam_lj, pos = self.dameJugadaEn( fila, columna.clave )
                    fen = jg.posicion.fen()
                siBlancas = " w " in fen
                if siBlancas :
                    siMB = numero in [1,2]
                else :
                    siMB = numero in [7,8]
                si2 = numero in [2,7]
                self.tablero.quitaFlechas()
                if self.tablero.flechaSC :
                    self.tablero.flechaSC.hide()
                self.ponFlechas( fen, siMB, siIzq, si2 )
            else :
                self.tablero.quitaFlechas()
                if self.tablero.flechaSC :
                    self.tablero.flechaSC.show()

    #--------------------------------------------------------------------------------------------------------------------------------
    def trasteros( self, orden  ) :

        if orden == "nuevo" :
            resp = QTUtil2.salvaFichero( self.pantalla, tr( "TRASTERO" ), self.configuracion.dirSalvados, tr("FICHERO")+" pgn (*.pgn)", False )
            if resp :
                carpeta,trastero = os.path.split( resp )
                if carpeta != self.configuracion.dirSalvados :
                    self.configuracion.dirSalvados = carpeta
                    self.configuracion.graba()

                siEsta = False
                for carpeta1, trastero1 in self.configuracion.liTrasteros :
                    if carpeta1.lower() == carpeta.lower() and trastero1.lower() == trastero.lower() :
                        siEsta = True
                        break

                if not siEsta :
                    self.configuracion.liTrasteros.append( (carpeta,trastero) )
                    self.configuracion.graba()

        elif orden.startswith("quitar"):
            nquitar = int( orden[7:] )
            del self.configuracion.liTrasteros[nquitar]
            self.configuracion.graba()

        else :
            carpeta, trastero = self.configuracion.liTrasteros[int(orden)]
            fichero = os.path.join( carpeta, trastero )
            dato = self.listado( "pgn" )
            if os.path.isfile( fichero ) :
                dato = "\r\n"*2 + dato
            try :
                f = codecs.open(fichero,"ab",'utf-8')
                f.write( dato )
                f.close()
                QTUtil2.mensaje( self.pantalla, tr( "GRABADO",fichero ) )
            except :
                QTUtil2.mensError( self.pantalla, "%s : %s\n"%( tr("IMPOSIBLE_GRABAR"),fichero ) )

    #--------------------------------------------------------------------------------------------------------------------------------
    def moscas( self, liMoscas, orden  ) :

        if orden == "nueva" :
            liMoscas = XMoscas.nuevaMosca( self.pantalla, self.configuracion )
            if liMoscas :
                self.moscas( liMoscas, str(len(liMoscas)-1))

        elif orden.startswith("quitar"):
            nquitar = int( orden[7:] )
            del liMoscas[nquitar]
            XMoscas.listaMoscasGrabar( self.configuracion, liMoscas )

        else :
            nmosca = int( orden )
            mosca = liMoscas[nmosca]
            xmosca = XMoscas.XMosca( self, mosca )
            self.liMoscasActivas.append( xmosca )
            self.ponVista()

    #--------------------------------------------------------------------------------------------------------------------------------
    def paraHumano(self) :
        self.siJuegaHumano = False
        self.desactivaTodas()

    #--------------------------------------------------------------------------------------------------------------------------------
    def sigueHumano(self) :
        self.siTeclaPanico = False
        self.siJuegaHumano = True
        self.activaColor( self.partida.ultPosicion.siBlancas )

    #--------------------------------------------------------------------------------------------------------------------------------
    def libros( self, apli, siVentanaPrincipal=True ) :

        # Se lee la lista de libros1
        listaLibros = Books.ListaLibros()
        fvar = self.configuracion.ficheroBooks
        listaLibros.recuperaVar( fvar )

        # Comprobamos que todos estén accesibles
        listaLibros.comprueba()

        # fens
        fenUltimo = self.partida.fenActual() # El último

        fenActual = self.fenActivo() # El de la posición en el tablero
        if self.partida.numJugadas() :
            fenPrevio = self.fenPrevio() # El de la posición previa
        else :
            fenPrevio = fenActual

        # iconos
        dicIco = { "w":Iconos.PuntoNaranja(), "b":Iconos.PuntoNegro(), "l":Iconos.TB_Libros(), "m":Iconos.PuntoAzul(), "c":Iconos.TB_Cancelar() }

        unLibro = None # Si miramos uno solo
        siPV = fenUltimo == fenActual

        while True : # bucle en caso de que queramos consultar otro libro

            liMenu0, liMenu1 = listaLibros.menus( apli, fenPrevio, fenActual, siPV, unLibro )

            # Menú
            menu = Controles.LMenu()
            f = Controles.TipoLetra( nombre="Courier New", puntos=10 )#, peso=65 )
            menu.ponFuente( f )

            if liMenu0 :
                clave, titulo, ico = liMenu0[0]
                menuAdicional = menu.submenu( titulo, dicIco[ico] )
                for clave, titulo, ico in liMenu0[1:] :
                    if titulo == None :
                        menu.separador()
                    else :
                        menu.opcion( clave, titulo, dicIco[ico] )
            else :
                menuAdicional = menu

            for clave, titulo, ico in liMenu1 :
                if titulo == None :
                    menuAdicional.separador()
                else :
                    menuAdicional.opcion( clave, titulo, dicIco[ico] )

            if siVentanaPrincipal :
                QtGui.QCursor.setPos( self.pantalla.base.pgn.mapToGlobal(QtCore.QPoint(0,0)) )
            resp = menu.lanza()

            if resp is None :
                return None

            baseResp = resp[0]
            if baseResp == "L" : # Consultar otro libro
                unLibro = listaLibros.lista[int(resp[1])]

            elif baseResp == "M" : # Mantenimiento
                mant = resp[1]
                # Nuevo
                if mant == "N" :
                    fbin = QTUtil2.leeFichero( self.pantalla, listaLibros.path, "bin", titulo = tr("LIBROS_POLYGLOT") )
                    if fbin :
                        listaLibros.path = os.path.dirname( fbin )
                        nombre = os.path.basename(fbin)[:-4]
                        b = Books.Libro("P", nombre, fbin, False )
                        listaLibros.nuevo( b )

                # Borrar
                elif mant == "B" :
                    menu = Controles.LMenu()
                    menu.ponFuente( f )

                    icoQuitar = Iconos.Trastero_Quitar()

                    for libro in listaLibros.lista :
                        menu.opcion( libro, libro.nombre, icoQuitar )

                    libro = menu.lanza()
                    if libro :
                        listaLibros.borra( libro )

                # Cambiar
                elif mant == "C" :
                    menu = Controles.LMenu()
                    menu.ponFuente( f )

                    ico = Iconos.TB_Aceptar()

                    for libro in listaLibros.lista :
                        menu.opcion( libro, libro.nombre, dicIco["l"] )

                    libro = menu.lanza()
                    if libro :

                        # Datos
                        liGen = [(None,None)]

                        ## nombre
                        config = FormLayout.Editbox( tr( "LIBROS_NOMBRE" ), ancho=280 )
                        liGen.append( (config, libro.nombre ) )

                        ## por defecto
                        liGen.append( ( tr("LIBROS_PORDEFECTO"), libro.pordefecto ) )

                        # Editamos
                        resultado = FormLayout.fedit( liGen, title= tr( "LIBROS_MODIFICAR" ), parent = self.pantalla, icon = Iconos.TB_Libros(), siDefecto = False )

                        if resultado :
                            accion, resp = resultado

                            nombre = resp[0]
                            if nombre :
                                libro.nombre = nombre
                                libro.pordefecto = resp[1]

                # Modo
                elif mant == "M" :
                    listaLibros.cambiaModo(apli)

                # Modo
                elif mant == "A" :
                    li = listaLibros.compruebaApertura( self.partida )
                    if li :
                        menu = Controles.LMenu()
                        menu.ponFuente( f )
                        for clave, txt, ico, liOp in li :
                            if liOp is None :
                                menu.separador()
                                menu.opcion( None, txt, dicIco[ico] )
                                menu.separador()
                            else :
                                menu1 = menu.submenu( txt, dicIco[ico] )
                                for txt in liOp :
                                    menu1.opcion( None, txt, dicIco[ico] )
                        resp = menu.lanza()

                    return None

                listaLibros.guardaVar( fvar )

            else :
                return resp

        return None

    #--------------------------------------------------------------------------------------------------------------------------------
    def compruebaDGT( self ) :
        if self.configuracion.siDGT :
            if not DGT.activarSegunON_OFF( self.dgt ) : # Error
                QTUtil2.mensError( self.pantalla, tr( "DGT_ERROR" )  )

    #--------------------------------------------------------------------------------------------------------------------------------
    def dgt( self, quien, a1h8 ) :

        if self.tablero.mensajero and self.tablero.siActivasPiezas :
            if quien == "whiteMove" :
                if not self.tablero.siActivasPiezasColor :
                    return 0
            elif quien == "blackMove" :
                if self.tablero.siActivasPiezasColor :
                    return 0
            elif quien == "scan" :
                return 1
            else :
                return 1

            if self.tablero.mensajero( a1h8[:2], a1h8[2:4], a1h8[4:] ) :
                return 1
            return 0

        return 1

    #--------------------------------------------------------------------------------------------------------------------------------
    def ponPosicion( self, posicion ) :
        self.tablero.ponPosicion( posicion )

    #--------------------------------------------------------------------------------------------------------------------------------
    def ponPosicionDGT( self ) :
        DGT.ponPosicion(self.partida)

