#!/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: bloquedialogo.py

"""Clase BloqueDialogo."""


from xml.dom import minidom
import random
import sys
import string
import os

from utils import *

class BloqueDialogo(object):
    """Clase abstracta con utilidades para los objetos de dialogo con los PNJ.
    
    Contiene los siguientes atributos:
     - id (string): identifica univocamente la conversacion. No puede contener espacios.
     - version (string): versión del sistema de dialogos.
     - autor (string): nombre del autor de la descripción.
     - pnj (string): nombre del pnj al que pertenece la conversacion.
     - comentario (string): comentario explicativo del fichero de conversacion.
    

    Invariantes:
      id != None
      version != None
      autor != None
      pnj != None
      comentario != None
    """

    # Version del sistema de descripcion de dialogos
    VERSION_DESC_DIALOGO = '1.0'

    # Version del sistema de dialogos 
    VERSION_DIALOGO = '1.1'

    DIR_DESC_DIALOGOS = 'desc_dialogos'
    EXT_DESC_DIALOGOS = '.xml'
    DIR_DIALOGOS = 'dialogos'
    EXT_DIALOGOS = ''
    
    TIPOS_DE_MENSAJES = ["pregunta", "respuesta", "entorno", "hito", "redireccion"]

    def __init__(self):
        pass

    # FUNCIONES DE EXTRACCION DE ITEMS
    
    def _parsear_fragmentos(self, item_xml):
    	"""Extrae toda la información de los fragmentos del item.

        item_xml: nodo XML de tipo item
        """
	
        from fragmento import Fragmento
	fragmentos = []
	
	for texto in item_xml.childNodes:
	    texto.normalize()
	    #escribir(self._mensaje_formateado(texto))
	    if texto.tagName in BloqueDialogo.TIPOS_DE_MENSAJES:
		fragmentos.append( Fragmento(texto, self) )
        return fragmentos
    
    def _parsear_temas_relacionados(self, item_xml):
    	"""Extrae toda la información de los temas relacionados del item."""
      
        relacionados = {}
        nodos_relacionados = item_xml.getElementsByTagName("relacionado")
        for nodo_tema in nodos_relacionados:
            relacionados[nodo_tema.getAttribute("nombre").encode('ISO-8859-1')] = nodo_tema.getAttribute("contexto").encode('ISO-8859-1')
        return relacionados
    
    def _parsear_items(self, tema_xml):
    	"""Extrae toda la información de los items del tema."""
        
        from item import Item
	items = []		
	nodos_item = tema_xml.getElementsByTagName("item")
	for item in nodos_item:
            items.append(Item(item, self))
        return items
    
    def _parsear_sinonimos(self, tema_xml):
        """Extrae la lista de sinonimos del tema."""
        sinonimos = []
	for nodo_sinonimo in tema_xml.getElementsByTagName("sinonimo"):
	    sinonimos.append(nodo_sinonimo.firstChild.data.encode('ISO-8859-1'))
        return sinonimos
    
    def _parsear_requisitos(self, item_xml):
    	"""Extrae toda la información de los requisitos del item."""
      
        requisitos = {}
        nodos_requisito = item_xml.getElementsByTagName("requisito")
        for requisito in nodos_requisito:
	    if requisito.getAttribute("valor"):
	        # Requisito con atributo "valor"
	        valor = requisito.getAttribute("valor").encode('ISO-8859-1')
	    elif requisito.firstChild:
	        # Requisito con nodo de texto
	        from fragmento import Fragmento
	        valor = Fragmento(requisito, self)
	    else:
	        # Antirequisito (requiere hito indefinido)
	        valor = None
            requisitos[requisito.getAttribute("nombre").encode('ISO-8859-1')] = valor
        return requisitos
    
    
    # FUNCIONES DE EXTRACCION DE TEMAS
	
    def _parsear_temas(self, contexto_xml):
    	"""Extrae toda la información de los temas del contexto."""
	
        from tema import Tema
	temas = []
	
	nodos_tema = contexto_xml.getElementsByTagName("tema")
	for tema in nodos_tema:
            temas.append(Tema(tema, self))
        return temas
    
	
    def _parsear_temas_especiales(self, nodoEspecial_xml):
    	"""Extrae toda la información de los temas agotados, offtopic y no encontrados."""
	
        from tema import TemaEspecial
        temasEspeciales = {"temaAgotado": [], "temaNoEncontrado": [], "temaOfftopic" : []}

        for tipo in ["temaAgotado", "temaNoEncontrado", "temaOfftopic"]:
            for nodo_tema in nodoEspecial_xml.getElementsByTagName(tipo):
                temasEspeciales[tipo].append(TemaEspecial(nodo_tema, tipo))
        return temasEspeciales
    
    # FUNCIONES DE EXTRACCION DE CONTEXTOS
	
    def _parsear_contextos(self, doc_xml):	
	"""Extrae toda la información de los contextos de la conversacion."""

	from contexto import Contexto
	nodo_contextos = doc_xml.getElementsByTagName("contextos")[0]
	
	contextos = []  
	for nodo_contexto in nodo_contextos.getElementsByTagName("contexto"):
            if (len(nodo_contexto.childNodes) == 0):
                # Carga el contexto desde fichero externo
                contexto_id = nodo_contexto.getAttribute("id").encode('ISO-8859-1')
                archivo = os.path.join(BloqueDialogo.DIR_DESC_DIALOGOS, contexto_id.split('-')[0], contexto_id + BloqueDialogo.EXT_DESC_DIALOGOS)
                stream = open(archivo)
                contexto_xml = minidom.parse(stream).documentElement
                stream.close()
                
                nodo_contexto = contexto_xml
#                escribir ("Contexto: " + nodo_contexto.getAttribute("id"))
                contextos.append(Contexto(nodo_contexto, self))
                contexto_xml.unlink()
            else:
                # Carga el contexto definido inline
                contextos.append(Contexto(nodo_contexto, self))
	    try:
                pass
	    except:
		escribir("Error al parsear contexto en conversacion "+self.id)
		pass
	return contextos
	        
    # UTILIDADES DE MANEJO DE XML
    def _limpiar_comentarios(self, doc_xml):
	"""Esta función borra todos los nodos de tipo Text de un
	elemento DOM. Se usa para eliminar comentarios del fichero XML."""
	
	for nodo in doc_xml.childNodes[:]:
	    if nodo.nodeType == nodo.TEXT_NODE:
		doc_xml.childNodes.remove(nodo)
		
        
parserXMLconversacion = BloqueDialogo()
	

# Código para pruebas unitarias del módulo.

if (__name__ == '__main__'):
    print "No hay prueba unitaria de módulo. "
