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

import os
from operator import itemgetter
import copy

from PySide import QtCore, QtGui

from Code.Traducir import tr

import Code.SQL as SQL
import Code.PGN as PGN

import QTUtil, QTUtil2
import Colocacion
import Iconos
import Controles

import Grid
import Columnas

import PantallaBooks

#==========================================================================================================================================
class EstadoWpgn :

    def guarda( self, window, dbf ) :

        # dbf
        self.select = dbf.select
        self.condicion = dbf.condicion
        self.orden = dbf.orden

        # grid
        grid = window.grid
        self.recno = grid.recno()
        self.dicVideoGrid = {}
        grid.guardarVideo( self.dicVideoGrid )

        # ventana
        self.pos = window.pos()
        self.tam = window.size()

        self.liOrdenClaves = window.liOrdenClaves
        self.liFiltro = window.liFiltro

    def recuperaDBF( self, dbf ) :
        dbf.select = self.select
        dbf.condicion = self.condicion
        dbf.orden = self.orden
        dbf.leer()

    def recuperaWindow( self, window ) :
        window.resize( self.tam )
        window.move( self.pos )

#==========================================================================================================================================
class WElegir( QtGui.QDialog ):

    def __init__( self, wParent, dbf, dClaves, gestor, estado = None ) :

        super(WElegir, self).__init__(wParent)

        dClaves = copy.deepcopy(dClaves)

        self.seHaBorradoAlgo = False # Para que se haga un touch antiguo al DB y lo regenere la próxima vez

        self.gestor = gestor

        siRepite = estado is not None
        if siRepite :
            self.estado = estado
        else :
            self.estado = EstadoWpgn()

        self.dbf = dbf
        if siRepite :
            self.estado.recuperaDBF(dbf)
        else :
            self.dbf.leer()

        # Filtro
        self.liFiltro = self.estado.liFiltro if siRepite else []

        self.setWindowTitle(  tr( "PGN_ROTELEGIR" ) )
        self.setWindowIcon( Iconos.PGN() )
        self.setWindowFlags( QtCore.Qt.Dialog | QtCore.Qt.WindowTitleHint | QtCore.Qt.WindowMinimizeButtonHint | QtCore.Qt.WindowMaximizeButtonHint)

        # Toolbar
        liAcciones = [  ( tr( "TB_PGNELEGIR" ), Iconos.TB_Aceptar(), "elegir" ), None,
                        ( tr( "CANCELAR" ), Iconos.TB_Cancelar(), "cancelar" ), None,
                        ( tr( "TB_PGNINICIO" ), Iconos.TB_Inicio(), "inicio" ),
                        ( tr( "TB_PGNFINAL" ), Iconos.TB_Final(), "final" ), None,
                        ( tr( "TB_PGNFILTRAR" ), Iconos.TB_Filtrar(), "filtrar" ), None,
                        ( tr( "TB_GUARDAR" ), Iconos.TB_Grabar(), "guardar" ), None,
                        ( tr( "BORRAR" ), Iconos.TB_Borrar(), "borrar" ), None,
                        ( tr( "LIBROS" ), Iconos.TB_Libros(), "libros" ), None
                    ]
        tb = Controles.TB( self, liAcciones )

        # Lista
        oColumnas = Columnas.ListaColumnas()
        oColumnas.nueva( "numero", tr( "AB_NUM" ), 50, siCentrado= True)
        def creaCol( clave, siCentrado = True ) :
            trclave = "PGN_" + clave
            rotulo = tr( trclave )
            if rotulo == trclave :
                rotulo = clave
            rotulo = rotulo[0].upper() + rotulo[1:].lower()
            tam = max( (dClaves[clave][0]), len(rotulo),11 )
            oColumnas.nueva( clave, rotulo, tam*6, siCentrado=siCentrado)

        ## Claves según orden estandar
        self.ordenEstandar =[ "EVENT", "SITE", "DATE", "ROUND", "WHITE", "BLACK", "RESULT", "ECO", "FEN" ]
        self.liOrdenClaves = [] # nos servira´en el exterior, para paste pgn y para mostrar info
        for clave in self.ordenEstandar :
            if clave in dClaves :
                creaCol( clave, clave != "EVENT" )
                del dClaves[clave]
                self.liOrdenClaves.append( clave )

        ## Resto de claves, según la posición
        li = [(k, dClaves[k][1]) for k in dClaves]
        li = sorted( li, key=itemgetter(1) )
        for clave, pos in li :
            creaCol( clave )
            self.liOrdenClaves.append( clave )

        dicVideoGrid = self.estado.dicVideoGrid if siRepite else None
        self.grid = Grid.Grid( self, oColumnas, siSelecFilas = True, dicVideo = dicVideoGrid )

        if siRepite :
            self.grid.goto( self.estado.recno, 0 )
        else :
            self.grid.gotop()

        if siRepite :
            self.estado.recuperaWindow( self )
        else :
            n = self.grid.anchoColumnas() +20
            w,h = QTUtil.tamEscritorio()
            self.resize( min( w*9/10, n ), h*8/10 )

        # Layout
        layout = Colocacion.V().control(tb).control(self.grid).margen( 3 )
        self.setLayout( layout )

    #--------------------------------------------------------------------------------------------------------------------------------
    def procesarTB( self ) :
        accion = self.sender().clave
        if accion == "elegir" :
            self.elegir()
        elif accion == "cancelar" :
            self.reject()
        elif accion == "inicio" :
            self.grid.gotop()
        elif accion == "final" :
            self.grid.gobottom()
        elif accion == "filtrar" :
            self.filtrar()
        elif accion == "guardar" :
            self.guardar()
        elif accion == "borrar" :
            self.borrar()
        elif accion == "libros" :
            self.libros()

    #--------------------------------------------------------------------------------------------------------------------------------
    def elegir( self ) :
        f,c = self.grid.posActualN()
        n = self.dbf.reccount()
        if f < n and f >= 0 :
            self.dbf.goto( f )
            self.estado.guarda(self,self.dbf)
            self.accept()

    #--------------------------------------------------------------------------------------------------------------------------------
    def gridDobleClick( self, grid, fila, oColumna ) :
        self.elegir()

    #--------------------------------------------------------------------------------------------------------------------------------
    def gridDobleClickCabecera( self, grid, oColumna ) :
        clave = oColumna.clave
        orden = self.dbf.orden
        if orden.startswith(clave) :
            siDesc = orden.endswith( "DESC" )
            if siDesc :
                orden = ""
            else :
                orden += " DESC"
        else :
            orden = clave
        self.dbf.orden = orden

        self.dbf.leer()
        self.grid.refresh()

    #--------------------------------------------------------------------------------------------------------------------------------
    def gridNumDatos( self, grid ) :
        return self.dbf.reccount()

    #--------------------------------------------------------------------------------------------------------------------------------
    def gridWheelEvent( self, quien, siAdelante ) :
        n = self.dbf.reccount()
        f, c = self.grid.posActualN()
        f += -1 if siAdelante else +1
        if f < n and f >= 0 :
            self.grid.goto( f, c )
    #--------------------------------------------------------------------------------------------------------------------------------
    def gridDato( self, grid, fila, oColumna ) :
        self.dbf.goto( fila )
        clave = oColumna.clave
        if clave == "numero" :
            return str(fila+1)
        valor = getattr( self.dbf, oColumna.clave )
        if valor is None :
            valor = ""
        if clave.endswith( "DATE" ) :
            valor = valor.replace( ".??", "" )
        if "?" in valor :
            valor = valor.replace( "?", "" )
        return valor

    #--------------------------------------------------------------------------------------------------------------------------------
    def filtrar( self ) :
        w = WFiltrar( self, self.grid.oColumnas, self.liFiltro )
        if w.exec_() :
            self.liFiltro = w.liFiltro

            where = ""
            for union, campo, condicion, valor in self.liFiltro :
                valor = valor.upper()
                if condicion == "LIKE" :
                    if "%" not in valor :
                        valor = "%" + valor + "%"

                if union :
                    where += " %s "% union
                if condicion in ( "=", "<>" ) and not valor :
                    where += "(( %s %s ) OR (%s %s ''))"%(campo, "IS NULL" if condicion == "=" else "IS NOT NULL", campo, condicion )
                else :
                    where += "UPPER(%s) %s '%s'"%(campo,condicion,valor.upper())

            self.dbf.condicion = where
            self.dbf.leer()
            self.grid.refresh()
            self.grid.gotop()

    #--------------------------------------------------------------------------------------------------------------------------------
    def guardar( self ) :
        extension = "pgn"
        resp = QtGui.QFileDialog.getSaveFileName( self, tr( "INDICA_FICHERO" ), self.gestor.configuracion.dirSalvados, tr("FICHERO")+" %s (*.%s)"%(extension,extension) )
        if resp and resp[0]:
            resp = resp[0]
            try :
                f = open( resp, "wb" )
                antSelect = self.dbf.select
                nueSelect = antSelect + ",JUGADAS"
                self.dbf.ponSelect( nueSelect )
                self.dbf.leer()
                self.dbf.gotop()
                for i in range(self.dbf.reccount()) :
                    self.dbf.goto(i)
                    dic = self.dbf.dicValores()
                    t = ""
                    for clave in self.liOrdenClaves :
                        valor = dic[clave]
                        if valor is not None :
                            t += '[%s "%s"]\n'%(clave,valor)

                    t += dic["JUGADAS"].replace( "#+", "#" ) + "\n"
                    t = t.replace( "\n\n", "\n" )
                    f.write( t )

                f.close()
                direc = os.path.dirname( resp )
                if direc != self.gestor.configuracion.dirSalvados :
                    self.gestor.configuracion.dirSalvados = direc
                    self.gestor.configuracion.graba()
                self.dbf.ponSelect( antSelect )
            except :
                QTUtil2.mensError( self, "%s : %s"%( tr("IMPOSIBLE_GRABAR"),resp ) )

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

        icoQuitar = Iconos.Trastero_Quitar()

        menu.opcion( "actual", tr( "PGN_BORRAR_ACTUAL" ), icoQuitar )

        if self.dbf.condicion :
            menu.separador()
            menu.opcion( "todos", tr( "PGN_BORRAR_TODOS" ), icoQuitar )
        resp = menu.lanza()
        if resp :
            li = []
            n = self.dbf.reccount()
            if resp == "actual" :
                f,c = self.grid.posActualN()
                if f < n and f >= 0 :
                    li.append(f)
                else :
                    return
            elif resp == "todos" :
                li = range(n)

            self.dbf.borrarLista( li )

            if resp == "todos" :
                self.dbf.condicion = ""

            self.seHaBorradoAlgo = True # Para que se haga un touch antiguo al DB y lo regenere
            self.dbf.leer()
            self.grid.refresh()

            if resp == "actual" :
                self.grid.goto( f, 0 )
            else :
                self.grid.gotop()

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

        ico = Iconos.PuntoAzul()

        menu1 = menu.submenu( tr( "LIBROS_POLYGLOT" ), ico )

        menu1.opcion( "crear", tr( "LIBROS_CREAR" ), ico )
        menu1.opcion( "unir", tr( "LIBROS_UNIR" ), ico )

        resp = menu.lanza()
        if resp :
            if resp == "crear" :
                PantallaBooks.polyglotCrear(self)
            else :
                PantallaBooks.polyglotUnir(self)

#==========================================================================================================================================
class WFiltrar( QtGui.QDialog ):

    def __init__( self, wParent, oColumnas, liFiltro ) :

        super(WFiltrar, self).__init__(wParent)

        self.setWindowTitle( tr( "TB_PGNFILTRAR" ) )
        self.setWindowFlags( QtCore.Qt.Dialog | QtCore.Qt.WindowTitleHint )

        self.liFiltro = liFiltro
        nFiltro = len(liFiltro)

        liCampos = [ (x.cabecera, x.clave) for x in oColumnas.liColumnas ]
        liCampos.insert( 0, ( "", None ) )
        liCondicion = [ ( "", None ),
                        ( tr("PGN_FILIGUAL"), "=" ),
                        ( tr("PGN_FILDISTINTO"), "<>" ),
                        ( tr("PGN_FILMAYORQUE"), ">" ),
                        ( tr("PGN_FILMENORQUE"), "<" ),
                        ( tr("PGN_FILMAYORIGUALQUE"), ">=" ),
                        ( tr("PGN_FILMENORIGUALQUE"), "<=" ),
                        ( tr("PGN_FILCOMO"), "LIKE" ) ]

        liUnion = [ ( "", None ),
                    ( tr("PGN_FILY"), "AND" ),
                    ( tr("PGN_FILO"), "OR" ) ]

        f = Controles.TipoLetra( puntos=12) #0, peso=75 )

        lbCol = Controles.LB( tr( "PGN_FILCOLUMNA" ) ).ponFuente( f )
        lbCon = Controles.LB( tr( "PGN_FILCONDICION" ) ).ponFuente( f )
        lbVal = Controles.LB( tr( "PGN_FILVALOR" ) ).ponFuente( f )
        lbUni = Controles.LB( "+" ).ponFuente( f )

        ly = Colocacion.G()
        ly.controlc( lbUni, 0, 0 ).controlc( lbCol, 0, 1 ).controlc( lbCon, 0, 2 ).controlc( lbVal, 0, 3 )

        self.numC = 4
        liC = []

        for i in range(self.numC) :
            if i > 0 :
                valor = None if nFiltro <= i else liFiltro[i][0]
                c_union = Controles.CB( liUnion, valor )
                ly.controlc( c_union, i+1, 0 )
            else :
                c_union = None
            valor = None if nFiltro <= i else liFiltro[i][1]
            c_campo = Controles.CB( liCampos, valor )
            ly.controlc( c_campo, i+1, 1 )
            valor = None if nFiltro <= i else liFiltro[i][2]
            c_condicion = Controles.CB( liCondicion, valor )
            ly.controlc( c_condicion, i+1, 2 )
            valor = "" if nFiltro <= i else liFiltro[i][3]
            c_valor = Controles.ED( self, valor )
            ly.controlc( c_valor, i+1, 3 )

            liC.append( (c_union, c_campo, c_condicion, c_valor) )

        self.liC = liC

        # Toolbar
        liAcciones = [  ( tr( "ACEPTAR" ), Iconos.TB_Aceptar(), "aceptar" ), None,
                        ( tr( "CANCELAR" ), Iconos.TB_Cancelar(), "cancelar" ), None,
                        ( tr( "TB_REINICIAR" ), Iconos.TB_Reiniciar(), "reiniciar" ), None,
                    ]
        tb = Controles.TB( self, liAcciones )

        # Layout
        layout = Colocacion.V().control(tb).otro(ly).margen( 3 )
        self.setLayout( layout )

    #--------------------------------------------------------------------------------------------------------------------------------
    def procesarTB( self ) :
        accion = self.sender().clave
        if accion == "aceptar" :
            self.aceptar()
        elif accion == "cancelar" :
            self.reject()
        elif accion == "reiniciar" :
            self.reiniciar()

    #--------------------------------------------------------------------------------------------------------------------------------
    def reiniciar( self ) :
        for i in range(self.numC) :
            self.liC[i][1].setCurrentIndex( 0 )
            self.liC[i][2].setCurrentIndex( 0 )
            self.liC[i][3].ponTexto( "" )
            if i > 0 :
                self.liC[i][0].setCurrentIndex( 0 )

    #--------------------------------------------------------------------------------------------------------------------------------
    def aceptar( self ) :

        self.liFiltro = []

        for i in range(self.numC) :
            campo = self.liC[i][1].resultado()
            condicion = self.liC[i][2].resultado()
            valor = self.liC[i][3].texto().rstrip()
            if campo and condicion :
                if i > 0 :
                    union = self.liC[i][0].resultado()
                    if union :
                        self.liFiltro.append( (union, campo, condicion, valor) )
                else :
                    self.liFiltro.append( (None, campo, condicion, valor) )
            else :
                break

        self.accept()

#==========================================================================================================================================
def elegirPGN( owner, dbf, dClaves, gestor, estado ) :
    w = WElegir( owner, dbf, dClaves, gestor, estado )
    if w.exec_() :
        return True, w.estado, w.seHaBorradoAlgo
    return False, None, w.seHaBorradoAlgo

#==========================================================================================================================================
def eligePartida( ventana, gestor ) :

    configuracion = gestor.configuracion
    # Elegimos el fichero PGN
    path = QTUtil2.leeFichero( ventana, gestor.configuracion.dirPGN, "pgn" )
    if not path  :
        return None
    carpeta, fichero = os.path.split(path)
    if configuracion.dirPGN != carpeta :
        configuracion.dirPGN = carpeta
        configuracion.graba()

    # Lo importamos
    fpgn = PGN.PGN()

    global tmpProceso, tmpBP
    tmpProceso = 0
    tmpBP = None

    def control( proceso, porcentaje ) :
        global tmpProceso, tmpBP
        if proceso != tmpProceso :
            if tmpProceso > 0 :
                tmpBP.cerrar()
                if proceso == 3 : #Nos ha mandado la señal de final
                    return True
            tmpProceso = proceso
            rotulo = tr( "PGN_F1LEYENDO", path ) if proceso == 1 else tr( "PGN_F2CONVIRTIENDO", path )
            tmpBP = QTUtil2.BarraProgreso( ventana, rotulo, rotulo, 100 ).mostrar()
        tmpBP.pon( porcentaje )
        return not tmpBP.siCancelado()

    dicDB = fpgn.leeFichero( path, control )
    if dicDB is None :
        return None

    # Los datos los tenemos en una BD.sql
    dClaves = dicDB["DICCLAVES"]

    bd = SQL.Base.DBBase( dicDB["PATHDB"] )

    dbf = bd.dbf( "JUEGOS", ",".join(dClaves.keys()) +",JUGADAS" )

    siSeguir, estadoWpgn, siSeHaBorradoAlgo = elegirPGN( ventana, dbf, dClaves, gestor, None )
    if siSeguir :
        reg = dbf.dicValores()

    dbf.cerrar()

    bd.cerrar()

    if not siSeguir :
        return

    pgn = ""
    for k,v in reg.iteritems() :
        if k != "JUGADAS" :
            pgn += '[%s "%s"]\n'%( k, v)
    pgn += reg["JUGADAS"]

    unpgn = PGN.UnPGN()
    unpgn.leeTexto(pgn)

    partida = unpgn.partida

    return partida

