import Ft
from blinkster.utils import zipfileext
import blinkster.utils.log
import blinkster.utils.xml
from blinkster import settings
from blinkster.ldt.models import Content, Segment
import xml.dom.minidom
import xml.dom.ext
import xml.xpath
import lucene

def Property(func):
    return property(**func()) 


class ContentIndexer(object):
        
        def __init__(self, contentList, writer, decoupage_blackList=settings.DECOUPAGE_BLACKLIST):
                self.__contentList = contentList
                self.__decoupage_blacklist = decoupage_blackList
                self.__writer = writer
                    
        @Property
        def decoupage_blacklist(): #@NoSelf
            doc = """get blacklist""" #@UnusedVariable
           
            def fget(self):
                if self.__decoupage_blacklist is None:
                    self.__decoupage_blacklist = ()
                return self.__decoupage_blacklist
               
            def fset(self, value):
                self.__decoupage_blacklist = value
               
            def fdel(self):
                del self.__decoupage_blacklist
               
            return locals()
                   
        def index_all(self):
            for content in self.__contentList:
                self.index_content(content)
                
        def index_content(self, content):
            
            blinkster.utils.log.debug("Indexing content : " + str(content.iri_id))
            filepath = content.iri_file_path()
            doc = xml.dom.minidom.parse(filepath)
            doc = Ft.Xml.Domlette.ConvertDocument(doc)        
                        
            self.__writer.deleteDocuments(lucene.Term("iri_id", content.iri_id))
            
            con = xml.xpath.Context.Context(doc, 1, 1, None)
            
            res = xml.xpath.Evaluate("/iri/body/ensembles/ensemble", context=con)

            for ensemble in res:
                ensembleId = ensemble.getAttributeNS(None, "id")
                
                for decoupageNode in ensemble.childNodes:
                    blinkster.utils.log.debug("Indexing content decoupage : " + repr(decoupageNode.nodeType) + " in " + repr(self.decoupage_blacklist))
                    if decoupageNode.nodeType != xml.dom.Node.ELEMENT_NODE or decoupageNode.tagName != "decoupage"  or decoupageNode.getAttributeNS(None, "id") in self.decoupage_blacklist:
                        continue
                    
                    decoupId = decoupageNode.getAttributeNS(None, "id")
                    res = xml.xpath.Evaluate("elements/element", decoupageNode)
                    for elementNode in res:
                        doc = lucene.Document()
                        elementId = elementNode.getAttributeNS(None, "id")
                        tags = elementNode.getAttributeNS(None, "tags")
                        author = elementNode.getAttributeNS(None, "author")
                        start_ts = int(elementNode.getAttributeNS(None, "begin"))
                        duration = int(elementNode.getAttributeNS(None, "dur"))
                        date_str = elementNode.getAttributeNS(None, "date")
                        
                        if tags is not None:                            
                            tags.replace(",", ";")
                        
                        if tags is None or len(tags) == 0:
                            tags = ""
                            restagnode = xml.xpath.Evaluate("tag/text()", elementNode)
                            for tagnode in restagnode:
                                tags = tags + " ; " + tagnode.data
                                
                        if tags is None or len(tags) == 0:
                            tags = ""
                            restagnode = xml.xpath.Evaluate("tags/tag/text()", elementNode)
                            for tagnode in restagnode:
                                tags = tags + " ; " + tagnode.data                            
    
                        title = ""
                        for txtRes in xml.xpath.Evaluate("title/text()", elementNode): 
                            title = title + txtRes.data 
                
                        abstract = ""
                        for txtRes in xml.xpath.Evaluate("abstract/text()", elementNode): 
                            abstract = abstract + txtRes.data 
                
                        doc.add(lucene.Field("iri_id", content.iri_id, lucene.Field.Store.YES, lucene.Field.Index.NOT_ANALYZED))
                        doc.add(lucene.Field("ensemble_id", ensembleId, lucene.Field.Store.YES, lucene.Field.Index.NO))
                        doc.add(lucene.Field("decoupage_id", decoupId, lucene.Field.Store.YES, lucene.Field.Index.NO))
                        doc.add(lucene.Field("element_id", elementId, lucene.Field.Store.YES, lucene.Field.Index.NO))
                        doc.add(lucene.Field("tags", tags, lucene.Field.Store.NO, lucene.Field.Index.ANALYZED))
                        doc.add(lucene.Field("title", title, lucene.Field.Store.NO, lucene.Field.Index.ANALYZED))
                        doc.add(lucene.Field("abstract", abstract, lucene.Field.Store.NO, lucene.Field.Index.ANALYZED))
                        doc.add(lucene.Field("all", " ".join([tags, title, abstract]), lucene.Field.Store.NO, lucene.Field.Index.ANALYZED))
            
                        seg = Segment(content=content,
                                      iri_id=content.iri_id,
                                      ensemble_id=ensembleId,
                                      cutting_id=decoupId,
                                      element_id=elementId,
                                      tags=tags,
                                      title=title,
                                      abstract=abstract,
                                      duration=duration,
                                      author=author,
                                      start_ts=start_ts,
                                      date=date_str)
                        seg.save()
            
                        self.__writer.addDocument(doc)
            
            self.__writer.commit()
            
            
class ProjectIndexer(object):
        
        def __init__(self, projectList, writer, decoupage_blackList=settings.DECOUPAGE_BLACKLIST):
                self.__projectList = projectList
                self.__decoupage_blacklist = decoupage_blackList
                self.__writer = writer
                
        @Property
        def decoupage_blacklist(): #@NoSelf
            doc = """get blacklist""" #@UnusedVariable
           
            def fget(self):
                if self.__decoupage_blacklist is None:
                    self.__decoupage_blacklist = ()
                return self.__decoupage_blacklist
               
            def fset(self, value):
                self.__decoupage_blacklist = value
               
            def fdel(self):
                del self.__decoupage_blacklist
               
            return locals()
                   
        def index_all(self):
            for project in self.__projectList:
                self.index_project(project)
 
        def index_project(self, project):
            
            blinkster.utils.log.debug("Indexing project : " + str(project.iri_id))
            doc = xml.dom.minidom.parseString(project.ldt)
            doc = Ft.Xml.Domlette.ConvertDocument(doc)        

            self.__writer.deleteDocuments(lucene.Term("iri_id", project.iri_id))
            
            con = xml.xpath.Context.Context(doc, 1, 1, None)
            res = xml.xpath.Evaluate("/iri/annotations/content", context=con)

            for content in res:
                contentId = content.getAttributeNS(None, "id")
                
                ensembleId = "ens_perso"
                
                for decoupageNode in content.childNodes:
                    blinkster.utils.log.debug("Indexing content decoupage : " + repr(decoupageNode.nodeType) + " in " + repr(self.decoupage_blacklist))
                    if decoupageNode.nodeType != xml.dom.Node.ELEMENT_NODE or decoupageNode.tagName != "decoupage"  or decoupageNode.getAttributeNS(None, "id") in self.decoupage_blacklist:
                        continue
                    
                    decoupId = decoupageNode.getAttributeNS(None, "id")
                    res = xml.xpath.Evaluate("elements/element", decoupageNode)
                    for elementNode in res:
                        doc = lucene.Document()
                        elementId = elementNode.getAttributeNS(None, "id")
                        tags = elementNode.getAttributeNS(None, "tags")
                        author = elementNode.getAttributeNS(None, "author")
                        start_ts = int(elementNode.getAttributeNS(None, "begin"))
                        duration = int(elementNode.getAttributeNS(None, "dur"))
                        date_str = elementNode.getAttributeNS(None, "date")
                        
                        if tags is not None:                            
                            tags.replace(",", ";")
                        
                        if tags is None or len(tags) == 0:
                            tags = ""
                            restagnode = xml.xpath.Evaluate("tag/text()", elementNode)
                            for tagnode in restagnode:
                                tags = tags + " ; " + tagnode.data
                                
                        if tags is None or len(tags) == 0:
                            tags = ""
                            restagnode = xml.xpath.Evaluate("tags/tag/text()", elementNode)
                            for tagnode in restagnode:
                                tags = tags + " ; " + tagnode.data                            
    
                        title = ""
                        for txtRes in xml.xpath.Evaluate("title/text()", elementNode): 
                            title = title + txtRes.data 
                
                        abstract = ""
                        for txtRes in xml.xpath.Evaluate("abstract/text()", elementNode): 
                            abstract = abstract + txtRes.data 
                
                
                        doc.add(lucene.Field("project_id", project.iri_id, lucene.Field.Store.YES, lucene.Field.Index.NOT_ANALYZED))              
                        doc.add(lucene.Field("iri_id", contentId, lucene.Field.Store.YES, lucene.Field.Index.NOT_ANALYZED))
                        doc.add(lucene.Field("ensemble_id", ensembleId, lucene.Field.Store.YES, lucene.Field.Index.NO))
                        doc.add(lucene.Field("decoupage_id", decoupId, lucene.Field.Store.YES, lucene.Field.Index.NO))
                        doc.add(lucene.Field("element_id", elementId, lucene.Field.Store.YES, lucene.Field.Index.NO))
                        doc.add(lucene.Field("tags", tags, lucene.Field.Store.NO, lucene.Field.Index.ANALYZED))
                        doc.add(lucene.Field("title", title, lucene.Field.Store.NO, lucene.Field.Index.ANALYZED))
                        doc.add(lucene.Field("abstract", abstract, lucene.Field.Store.NO, lucene.Field.Index.ANALYZED))
                        doc.add(lucene.Field("all", " ".join([tags, title, abstract]), lucene.Field.Store.NO, lucene.Field.Index.ANALYZED))
            
                        try:
                            content = Content.objects.get(iri_id=contentId)
                            seg = Segment(project_obj=project,
                                      content=content,
                                      project_id=project.ldt_id,
                                      iri_id=contentId,
                                      ensemble_id=ensembleId,
                                      cutting_id=decoupId,
                                      element_id=elementId,
                                      tags=tags,
                                      title=title,
                                      abstract=abstract,
                                      duration=duration,
                                      author=author,
                                      start_ts=start_ts,
                                      date=date_str)
                            seg.save()
                        except:
                            blinkster.utils.log.error("unable to store segment")
                            
            
            
                        self.__writer.addDocument(doc)
            
            self.__writer.flush()
