# -*- coding: latin-1 -*-
import os
import operator

from Traducir import tr

import Jugada

#------------------------------------------------------------------------------------------------------
class ElemGM :
    def __init__( self ) :
        self.juega = ""
        self.GM = ""
        self.partida = 0
        self.movimiento = ""
        self.coronacion = " "
        self.siguiente = 0
        self.siguienteByte = 0
        self.siHijos = False

    def __str__( self ) :
        return self.movimiento + ","+str(self.partida)+","+str(self.siguienteByte)

    def a1_num( self, a1 ) :
        letra = a1[0]
        numero = int(a1[1])
        letra = ord(letra) - 96
        return letra*10+numero

    def num_a1( self, cnum ) :
        num = ord(cnum)
        letra = chr(int(num/10)+96)
        numero = str(num%10)
        return letra+numero

    def tresBytes( self, n ) :
        n1 = n%256
        n -= n1
        n /= 256
        n2 = n%256
        n -= n2
        n /= 256
        n3 = n
        return n3, n2, n1

    def escribe( self, f ) :
        desde = self.movimiento[:2]
        hasta = self.movimiento[2:]
        n3, n2, n1 = self.tresBytes(self.siguienteByte)
        np3, np2, np1 = self.tresBytes(self.partida)

        f.write( chr(self.a1_num(desde)) + chr(self.a1_num(hasta)) )

        f.write( chr(n3) + chr(n2) + chr(n1) )

        f.write( chr(np2) + chr(np1) ) # Como maximo 5000
        f.write( self.coronacion )

    def tres_bytes_num( self, c3, c2, c1 ) :
        return ord(c3)*256*256 + ord(c2)*256 + ord(c1)

    def lee( self, f ) :
        bloque = f.read( 8 )
        desde = self.num_a1( bloque[0] )
        hasta = self.num_a1( bloque[1] )
        self.siguienteByte = self.tres_bytes_num( bloque[2], bloque[3], bloque[4] )
        self.partida = self.tres_bytes_num( "\0", bloque[5], bloque[6] )

        n = ord(bloque[7])
        self.siHijos = n > 128
        if self.siHijos :
            n -= 128
        self.coronacion = chr(n).strip().lower()
        self.movimiento = (desde + hasta + self.coronacion).strip()

#------------------------------------------------------------------------------------------------------
class RegGM :
    def __init__( self, gm, siBlancas ) :
        self.liElementos = []
        self.offset = 0
        self.gm = gm
        self.siBlancas = siBlancas
    def __str__( self ) :
        x = ""
        for el in self.liElementos :
            x += str(el) + ";"
        x = x.strip(";")
        return x
    def tam( self ) :
        return 1 + len(self.liElementos)*8
    def escribe( self, f ) :
        f.write( chr(len(self.liElementos)) )
        for el in self.liElementos :
            el.escribe( f )

    def lee( self, f ) :
        nElem = ord(f.read( 1 ))

        for i in range(nElem) :
            el = ElemGM()
            el.lee( f )
            self.liElementos.append( el )

    def siValido( self, desde, hasta, coronacion ) :
        if coronacion :
            coronacion = coronacion.lower()
        else :
            coronacion = ""
        movimiento = desde + hasta
        for n, el in enumerate(self.liElementos) :
            if el.movimiento == (movimiento+coronacion) :
                return el
        return None

    def dameJugadas( self ) :
        li = []
        for n, el in enumerate(self.liElementos) :
            li.append( (el.movimiento[:2], el.movimiento[2:4], el.coronacion, self.rotuloPartida( el.partida, False ) if not el.siHijos else None ) )
        return li

    def partidaActual( self ) :
        if len(self.liElementos) == 1 :
            el = self.liElementos[0]
            return self.liElementos[0].partida if not el.siHijos else -1
        else :
            return -1

    #-----------------------------------------------------------------------------------------------------------------
    def datosPartida( self, numero ) :
        txt = self.liPartidas[numero]
        oponente, fecha, apertura, result,color = txt.split( "·" )
        return oponente, fecha, apertura, result

    #-----------------------------------------------------------------------------------------------------------------
    def rotuloPartida( self, num, siGM=True ) :
        if num >= 0 :
            oponente, fecha, apertura, result = self.datosPartida( num )
            if siGM :
                return tr( "GM_OPONENTE" ) + " : <b>%s (%s)</b>"%( oponente, fecha )
            else :
                return "%s (%s)"%( oponente, fecha )

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

#==========================================================================================================================================
class GM :
    #-----------------------------------------------------------------------------------------------------------------
    def __init__( self, gm, siBlancas ) :
        self.offset = 0

        self.siBlancas = siBlancas
        self.gm = gm

        self.dicAciertos = {}

    #-----------------------------------------------------------------------------------------------------------------
    def lee( self ) :
        gm = self.gm
        color = "w" if self.siBlancas else "b"

        ficheroGM = gm + ".gm"+color
        f = open( "gm/"+ficheroGM, "rb" )
        f.seek( self.offset )
        self.rgm = RegGM(gm, self.siBlancas)
        self.rgm.lee(f)
        f.close()

        ficheroI = gm + ".gmi"
        f = open( "gm/"+ficheroI, "rb" )
        txt = f.read()
        f.close()
        self.liPartidas = txt.split( "\n" )
        self.rgm.liPartidas = self.liPartidas

    #-----------------------------------------------------------------------------------------------------------------
    def compruebaHumano( self, desde, hasta, coronacion ) :
        self.lee()

        acierto = self.rgm.siValido( desde, hasta, coronacion )
        if self.offset not in self.dicAciertos :
            self.dicAciertos[self.offset] = acierto

        return acierto

    #-----------------------------------------------------------------------------------------------------------------
    def haJugadoHumano( self, desde, hasta, coronacion ) :
        self.el = self.rgm.siValido( desde, hasta, coronacion )
        self.offset = self.el.siguienteByte

    #-----------------------------------------------------------------------------------------------------------------
    def rotuloPartidaActual( self ) :
        return self.rgm.rotuloPartida( self.rgm.partidaActual() )

    #-----------------------------------------------------------------------------------------------------------------
    def siTerminada( self ) :
        return self.offset == 0

    #-----------------------------------------------------------------------------------------------------------------
    def resultado( self, partida ) :
        oponente, fecha, apertura, result = self.rgm.datosPartida( self.el.partida )
        if partida.apertura :
            apertura = tr( partida.apertura.nombre )
        txt = tr( "GM_OPONENTE" ) + " : <b>" + oponente + "</b><br>"
        txt += tr( "GM_FECHA" ) + " : <b>" + fecha + "</b><br>"
        txt += tr( "PGN_OPENING" ) + " : <b>" + apertura + "</b><br>"
        txt += tr( "GM_RESULTADO" ) + " : <b>" + result + "</b><br>"
        txt += "<br>"*2
        aciertos = 0
        for v in self.dicAciertos.itervalues() :
            if v :
                aciertos += 1
        total = len(self.dicAciertos)
        if total :
            txt += tr( "GM_ACIERTOS" ) + " : <b>%d%%</b>"%int( aciertos*100.0/total )
        return txt

    #-----------------------------------------------------------------------------------------------------------------
    def datosActuales( self ) :
        return self.rgm.datosPartida( self.el.partida )

    #-----------------------------------------------------------------------------------------------------------------
    def dameJugadasTXT( self, posicionBase ) :
        li = []
        for desde, hasta, coronacion, rotulo in self.rgm.dameJugadas() :
            siBien, mens, jg = Jugada.dameJugada( posicionBase, desde, hasta, coronacion )
            if siBien :
                li.append( (desde, hasta, coronacion, rotulo, jg.pgnSP()) )
        return li

    #-----------------------------------------------------------------------------------------------------------------
    def juegaMotor( self ) :
        self.lee()
        li = self.rgm.dameJugadas()
        n = len(li)
        if n == 0 :
            return None
        else :
            return li

    #-----------------------------------------------------------------------------------------------------------------
    def ponOffset( self, offset ) :
        self.offset = offset
        #~ self.rgm.offset = offset

#==========================================================================================================================================
def dicGM( ) :
    dic = {}
    f = open( "gm/listaGM.txt", "rb" )
    for linea in f :
        if linea :
            li = linea.split( "·" )
            gm = li[0].lower()
            nombre = li[1]
            dic[gm] = nombre
    f.close()

    return dic

#==========================================================================================================================================
def listaGM() :
    dic = dicGM()
    li = []
    for fich in os.listdir( "Gm" ) :
        fich = fich.lower()
        if fich.endswith( ".gmw" ) :
            gm = fich[:-4].lower()
            try :
                li.append( (dic[gm], gm ) )
            except :
                pass
    li = sorted(li, key=operator.itemgetter(0))
    return li
#==========================================================================================================================================
