class Indexer(object):
    def __init__(self, collection, doStats=False, postingsFile=False):
        self.collection = collection
        self.lexAnalyser = False
        self.calculateStats = doStats
        self.vocabulary = Vocabulary()
        self.postings = DictionaryPostings({})
        self.documents = Documents()
        self.maxFreqInDocs = {}
        #self.positions = DictionaryPostings({})
        if self.calculateStats:
            self.stats = self.getInitStats()

    def index(self, config):
        """Indexa la coleccion dada"""

        # Configuro el analizador lexico
        self.lexAnalyser = LexAnalyser(config)

        #-----------------LEER-COLECCION--------------#
        docId = 0
        totalDocs = len(self.collection.allFiles())
        number_of_logs = 1 if totalDocs < 50 else totalDocs / 50
        for filePath in self.collection.allFiles():
            if (not filePath.lower().endswith('.txt')):
                logging.warning("following file will not be indexed: " +
                                filePath)
                continue

            # Guardo los datos del archivo actual
            actualDoc = {
                "name": os.path.basename(os.path.normpath(filePath)),
                "path": filePath
            }

            #----------LEER-ARCHIVO--------------------#
            if (docId + 1) % number_of_logs == 0:
                logging.info("Cargando %s (%d/%d)" %
                             (actualDoc["name"], docId + 1, totalDocs))
            with codecs.open(filePath, mode='rt', encoding='utf-8') as f:

                # Guardo tokens y terminos del documento
                tokens = []
                terms = []

                for line in f:
                    # Aplica tokenizado, stopwords y demas (segun config)
                    analysed = self.lexAnalyser.analyse(line)
                    terms.extend(analysed["terms"])
                    tokens.extend(analysed["tokens"])
                    analysed = None

            # Guardo documento actual
            self.documents.addDocument(docId, actualDoc["path"])

            # De cada documento los terminos que tiene (sin repetir)
            #self.documentsTerms[docId] = set()

            # Actualizo vocabulario
            self.updateIndex(docId, terms)
            #Actualizo stats
            if self.calculateStats:
                self.updateStats(tokens, terms)

            tokens = None
            terms = None
            docId += 1
            #------FIN-LEER-ARCHIVO--------------------#

        #----------------FIN-LEER-COLECCION---------#
        if self.calculateStats:
            logging.info("Generando stats")
            self.endStats()

        #logging.info(u"Ordenando vocabulario alfabeticamente")
        #self.vocabulary.setAlphabeticalOrder()
        #logging.info(u"Generando id de los terminos")
        #self.setTermsId()
        #logging.info(u"Ordenando postings por clave")
        #self.postings.sortByKey()
        #self.positions.sortByKey()
        #logging.info(u"Calculando frecuencias maximas de cada documento")
        #self.loadMaxFreqs()

    def updateIndex(self, docId, terms):
        position = 0
        termToFreq = {}
        for t in terms:
            #self.documentsTerms[docId].add(t)
            # Si termino no esta en vocabulario lo agrego inicializando la data
            if not self.vocabulary.isATerm(t):
                termId = self.vocabulary.addTerm(t, 1.0, 1.0)
                #self.postings.addPosting(termId, docId, 1.0)
                #self.positions.addPosting(t, docId, [position])
                termToFreq[termId] = 1
            else:
                self.vocabulary.incrementCF(t, 1.0)
                # termino no estaba en este documento?
                termId = self.vocabulary.getId(t)
                if not termId in termToFreq:
                    termToFreq[termId] = 1
                    self.vocabulary.incrementDF(t, 1.0)
                    #self.postings.addDocToPosting(termId, docId, 1.0)
                    #self.positions.addDocToPosting(t, docId, [position])
                # else termino ya existe en documento:
                else:
                    termToFreq[termId] += 1
                    # Actualizo postings con frecuencias
                    #self.postings.addDocToPosting(termId, docId, self.postings.getValue(termId, docId) + 1.0)
                    # Actualizo postings posicionales
                    #positionList = self.positions.getValue(t, docId)
                    #positionList.append(position)
                    #self.positions.addDocToPosting(t, docId, positionList)
            #position += 1
        for tId in termToFreq:
            self.postings.addPosting(tId, docId, termToFreq[tId])
        maxValue = 0
        for t in termToFreq:
            if termToFreq[t] >= maxValue:
                maxValue = termToFreq[t]
        termToFreq = None
        self.maxFreqInDocs[docId] = maxValue

    def getInitStats(self):
        out = {
            "tokens_count": 0.0,
            "terms_count": 0.0,
            "docs_count": 0.0,
            "longestDoc": {
                "tokens_count": -1,
                "terms_count": -1
            },
            "shortestDoc": {
                "tokens_count": sys.maxint,
                "terms_count": sys.maxint
            }
        }
        return out

    def updateStats(self, tokens, terms):
        tokensLength = len(tokens)
        termsLength = len(set(terms))

        self.stats["tokens_count"] += tokensLength
        self.stats["docs_count"] += 1.0

        # Documento es el mas grande?
        if tokensLength >= self.stats["longestDoc"]["tokens_count"]:
            self.stats["longestDoc"]["tokens_count"] = tokensLength
            self.stats["longestDoc"]["terms_count"] = termsLength
        # Documento es el mas pequeno?
        if tokensLength <= self.stats["shortestDoc"]["tokens_count"]:
            self.stats["shortestDoc"]["tokens_count"] = tokensLength
            self.stats["shortestDoc"]["terms_count"] = termsLength

    def endStats(self):
        nuberOfTerms = len(self.vocabulary.content)
        self.stats["terms_count"] = nuberOfTerms

        if self.stats["docs_count"] == 0:
            self.stats["avg_tokens_by_doc"] = 0
            self.stats["avg_terms_by_doc"] = 0
        else:
            self.stats["avg_tokens_by_doc"] = self.stats[
                "tokens_count"] / self.stats["docs_count"]
            self.stats["avg_terms_by_doc"] = self.stats[
                "terms_count"] / self.stats["docs_count"]

        self.stats["avg_term_length"] = 0 if nuberOfTerms == 0 else sum(
            [len(key)
             for key in self.vocabulary.content]) / (nuberOfTerms + 0.0)
        self.stats["terms_freq_one"] = len([
            key for key in self.vocabulary.content
            if self.vocabulary.getCF(key) == 1
        ])

    def printStatsFile(self, title):
        with open(title, "w") as statsFile:
            s = []
            s.append("-" * 50 + "\n")
            s.append("\tESTADISTICAS \tpor Juan Cardona\n")
            s.append("-" * 50 + "\n")
            s.append("Cantidad de Documentos Procesados: %d\n" %
                     self.stats["docs_count"])
            s.append("Cantidad de Tokens Extraidos: %d\n" %
                     self.stats["tokens_count"])
            s.append("Cantidad de Términos Extraidos: %d\n" %
                     self.stats["terms_count"])
            s.append("Cantidad Promedio de Tokens por Documento: %.2f\n" %
                     self.stats["avg_tokens_by_doc"])
            s.append("Cantidad Promedio de Términos por Documento: %.2f\n" %
                     self.stats["avg_terms_by_doc"])
            s.append("Largo promedio de un término: %.2f\n" %
                     self.stats["avg_term_length"])
            s.append("Cantidad de tokens del documento más corto: %d\n" %
                     self.stats["shortestDoc"]["tokens_count"])
            s.append("Cantidad de términos del documento más corto: %d\n" %
                     self.stats["shortestDoc"]["terms_count"])
            s.append("Cantidad de tokens del documento más largo: %d\n" %
                     self.stats["longestDoc"]["tokens_count"])
            s.append("Cantidad de términos del documento más largo: %d\n" %
                     self.stats["longestDoc"]["terms_count"])
            s.append(
                "Cantidad de términos que aparecen 1 vez en la colección: %d\n"
                % self.stats["terms_freq_one"])
            statsFile.write(''.join(s))
        return title