#!/usr/bin/env python
# encoding: iso-8859-15
#
#Minë. Mundo Interactivo-Narrativo en Español [Tierra-Media]
#Copyright (C) 2002  Pablo Ruiz Múzquiz
#
#
#This program is free software; you can redistribute it and/or modify
#it under the terms of the GNU General Public License as published by
#the Free Software Foundation; either version 2 of the License, or
#(at your option) any later version.
#
#This program is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#GNU General Public License for more details.
#
#You should have received a copy of the GNU General Public License
#along with this program; if not, write to the Free Software
#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#

#Fichero: actualizar-desc-salas.py

"""Script para actualizar todos los ficheros de descripcion de salas a la ultima version.

Se recorren todos los ficheros .xml del subdirectorio desc_salas y se realizan todos
los cambios necesarios para que puedan ser aceptados por la ultima version de Mine.
Algunas versiones puede que no se puedan convertir de forma totalmente automatica y
haya que hacer algo a mano. En esos casos se mostrara un texto explicativo.

Se salva una copia de los ficheros originales con extension .xml.bkp, por si hay algun
problema.  Al terminar el script se da la opcion de borrar las copias o conservarlas.

Forma de invocacion: desde el directorio raiz de Mine, escribir

    python actualizar-desc-salas.py

"""

import os
import sre


def averiguar_version(contenido):
    """Analiza el contenido y busca la linea con la version. Devuelve la version
    propiamente dicha, la linea entera y su posicion dentro del contenido.
    """
    for i in range(0, len(contenido)):
	linea = contenido[i]
	if linea.find('<sala') >= 0:
	    version_attr = sre.search('version="[0-9\.]*"', linea)
	    if version_attr == None:
		raise Exception, "La sala no tiene numero de version"
	    version = linea[version_attr.start()+9 : version_attr.end()-1]
	    break
    else:
	raise Exception, "No se ha encontrado descripcion de sala"

    return (version, linea, i)


def convertir_contenido(contenido, conversiones):
    """Esta es la funcion que hace el trabajo real. Recibe una lista de strings,
    uno por cada linea del fichero, y modifica los que sean necesarios. Al final
    devuelve true si no ha habido errores y ha cambiado algo del contenido.
    
    El parametro conversiones es un diccionario que se actualiza si se
    ha convertido el fichero con exito. Si por ejemplo, el fichero era de la
    version 1.0 y se ha subido a la 1.2, al diccionario le seran añadidas las
    siguientes claves: { "1.0":1, "1.1":1 }.
    """

    try:

	convertido_ok = 0

	(version, linea_version, nlinea_version) = averiguar_version(contenido)

	while version != "1.2":
	    
	    if version == "1.0":
		
		# Versión 1.0 -> 1.1: no hay que modificar el fichero (excepto el numero de
		# version), porque los cambios consisten en añadir tags nuevos.
		print "->Convirtiendo a versión 1.1"
		version = "1.1"
		contenido[nlinea_version] = linea_version.replace("1.0", "1.1")
		convertido_ok = 1
		conversiones["1.0"] = 1

	    elif version == "1.1":

		# Versión 1.1 -> 1.2: cambiar horario y error en las salidas por tipo_cierre,
		# datos_cierre y mensaje_cerrado.
		print "->Convirtiendo a versión 1.2"
		version = "1.2"
		for i in range(0, len(contenido)):
		    linea = contenido[i]
		    if sre.search('horario=".*"', linea) != None:
			contenido[i] = linea.replace('horario=', 'tipo_cierre="horario" datos_cierre=')
		    if sre.search('error=".*"', linea) != None:
			contenido[i] = linea.replace('error=', 'mensaje_cerrado=')
		contenido[nlinea_version] = linea_version.replace("1.1", "1.2")
		convertido_ok = 1
		conversiones["1.1"] = 1

	    else:
		raise Exception, "Numero de version desconocido: " + version

	return convertido_ok

    except Exception, msg_error:

	print "->" + str(msg_error) + ". Fichero no analizado."
	return 0


def convertir_fichero(nombre_fichero, conversiones):
    """Funcion generica que convierte un fichero: lo lee en memoria, convierte
    el contenido y luego lo vuelve a escribir. El fichero original se guarda
    añadiendole la extension .bkp.
    """

    print "Analizando fichero " + nombre_fichero + "..."
    fichero = open(nombre_fichero)
    contenido = fichero.readlines()
    fichero.close()

    convertido_ok = convertir_contenido(contenido, conversiones)

    if convertido_ok:
	print "->Convertido OK"
	os.rename(nombre_fichero, nombre_fichero + ".bkp")
	fichero = open(nombre_fichero, "w")
	fichero.writelines(contenido)
	fichero.close()


def convertir_directorio(nombre_directorio, conversiones):
    """Función genérica que convierte todos los ficheros de un directorio."""
    print "Entrando en directorio", nombre_directorio
    os.chdir(nombre_directorio)
    for nombre_fichero in os.listdir("."):
	if os.path.isdir(nombre_fichero):
	    convertir_directorio(nombre_fichero, conversiones)
	elif sre.match(".*\.xml$", nombre_fichero):
	    convertir_fichero(nombre_fichero, conversiones)
    os.chdir("..")


def borrar_bkp(nombre_directorio):
    """Función que borra todos los .bkp del directorio e inferiores."""
    os.chdir(nombre_directorio)
    for nombre_fichero in os.listdir("."):
	if os.path.isdir(nombre_fichero):
	    borrar_bkp(nombre_fichero)
	elif sre.match(".*\.xml\.bkp$", nombre_fichero):
	    os.remove(nombre_fichero)
    os.chdir("..")


# Punto de entrada del script, que convierte todos los ficheros
# con extension .xml del directorio desc_salas e inferiores.

conversiones = {}

convertir_directorio("./desc_salas", conversiones)

if len(conversiones) > 0:
    while 1:
      print "Durante la conversion se han guardado copias de los ficheros originales"
      print "de descripcion de salas, con el mismo nombre y extension .bkp. Ahora"
      print "puedes borrar los ficheros de copia, o conservarlos."
      borrar_los_bkp = raw_input("¿Borrar ficheros .bkp?: ").lower()
      if borrar_los_bkp == "s" or borrar_los_bkp == "si":
	  borrar_bkp("./desc_salas")
	  break
      elif borrar_los_bkp == "n" or borrar_los_bkp == "no":
	  break

if conversiones.has_key("1.0"):
    print """
Se han convertido ficheros de version 1.0. Hay que revisarlos a mano para
añadir articulos en los titulos de sala, las salidas y los nombres de
objetos (los articulos iran en minusculas). Por ejemplo, cambiar
    <nombre>Salon principal de la posada</nombre>
por
    <nombre>el salon principal de la posada</nombre>
"""

