#script pentru determinarea contextului unui text
import os
import sys
import math
import time
import datetime
from vars import SYS_PATH
os.environ["DJANGO_SETTINGS_MODULE"] = "news.settings"
sys.path.append(SYS_PATH)

from django.conf import settings
from news.stiri.models import Articol
from news.engine.compute_poisson import LoadPoisson
from news.engine.functions import elimina_sufixe
from news.utils import get_news_logger

class Context(object):
    """Clasa ce preia un text si returneaza cele mai importante cuvinte ale acestuia
    """
    
    def __init__(self, text, nr_cuvinte=10):
        self.text = text
        self.nr_cuvinte = nr_cuvinte
        self.nr_articole = self.get_numar_articole()
        self.cuvinte_input = self.stemming(self.text)
        self.dict_poisson = self.get_dict_poisson()
        self.cuvinte_context = self.compute_poisson(self.cuvinte_input, self.dict_poisson)
        self.lista_cuvinte = self.order_cuvinte(self.cuvinte_context, self.nr_cuvinte)
        
    def get_dict_poisson(self):
        poisson_loader = LoadPoisson()
        return poisson_loader.dict_poisson
        
    def stemming(self, text):
        #aplica stemming asupra textului de intrare
        #self.dict_cuvinte["teatru"] = ['nr_aparitii_cuvant': 3, 'cuvinte_asem': ["teatrul", "teatru", "Teatrul"]]
        dict_cuvinte = {}
        sir_strips = ",.;\"()<>?!:" 
        lista_cuvinte = text.split()
        for cuvant in lista_cuvinte:
            cuvant = cuvant.strip(sir_strips)
            if len(cuvant) >= 3:
                cuvant_lower = elimina_sufixe(cuvant).lower() 
                if dict_cuvinte.has_key(cuvant_lower):
                    if cuvant not in dict_cuvinte[cuvant_lower]['cuvinte_asem']:
                        dict_cuvinte[cuvant_lower]['cuvinte_asem'].append(cuvant)
                    dict_cuvinte[cuvant_lower]['nr_aparitii_cuvant'] += 1
                else:
                    dict_cuvinte[cuvant_lower] = {'nr_aparitii_cuvant': 1, 'cuvinte_asem': [cuvant]}
        return dict_cuvinte
        
    def compute_poisson(self, cuvinte_input, dict_poisson):
        #calculeaza greutatea Poisson
        #cuvinte_input['teatru'] = ['nr_aparitii_cuvant': 3, 'cuvinte_asem': ["teatrul", "teatru", "Teatrul"]]
        cuvinte_context = {}
        cuvinte = cuvinte_input.keys()
        for cuvant in cuvinte:
            if not cuvinte_context.has_key(cuvant):
                if dict_poisson.has_key(cuvant):
                    #XXX - comentam pentru moment, desi asa ar fi corect
                    nr_aparitii = dict_poisson[cuvant]['nr_total_aparitii'] + 1
                    #nr_aparitii = len(dict_poisson[cuvant]['lista_indecsi'])
                    aparitii_articol = len(dict_poisson[cuvant]['lista_indecsi'])
                else:
                    nr_aparitii = cuvinte_input[cuvant]['nr_aparitii_cuvant']
                    aparitii_articol = 1
                if self.nr_articole:
                    lmbd = (nr_aparitii * 1.0 / self.nr_articole)
                else:
                    lmbd = 0
                poisson0 = math.exp((-1) * lmbd)
                intermed = self.nr_articole * (1 - poisson0)
                overest = (intermed * 1.0 / aparitii_articol)
                cuvinte_context[cuvant] = overest
        return cuvinte_context
        
    def order_cuvinte(self, cuvinte_context, nr_cuvinte):
        #ordoneaza cuvintele dupa importanta lor, maxim nr_cuvinte
        lista_temp = [[value, key] for key, value in cuvinte_context.iteritems()]
        lista_temp.sort()
        lista_temp.reverse()
        return [{'cuvinte': self.cuvinte_input[item[1]]['cuvinte_asem'], 'overest': item[0]} 
                    for item in lista_temp[:nr_cuvinte]]
   
    def get_important_kws(self, cuvinte_context):
        #returneaza cele mai importante self.nr_cuvinte termeni cheie
        lista_temp = [[value, key] for key, value in cuvinte_context.iteritems()]
        lista_temp.sort()
        lista_temp.reverse()
        return [item[1] for item in lista_temp[:self.nr_cuvinte]]

    def get_numar_articole(self):
        """
        Returneaza numarul de articole pentru calculul Poisson
        """
        today = datetime.date.today()        
        start_date = today - datetime.timedelta(days=settings.NR_ZILE_ARTICOLE)
        numar_articole = Articol.objects.filter(data__gte=start_date).count()
        if not numar_articole:
            numar_articole = 3000
        return numar_articole
        
if __name__ == '__main__':
    inceput = time.time()
    text = """In consecinta, daca Claudiu si Martin ar fi de acord, am gasit impreuna 
            cu Simona o "semi"-solutie: daca nu se sperie clientii, sa ii punem sa 
            completeze pe cererea de credit valoarea maxima pe care se incadreaza, 
            ca oricum nu i se finanteaza mai mult de 75%. Pentru cei care sunt la 
            limita cu venitul, sa le explicam foarte clar ce surprize pot aparea.
           """
    nr_cuvinte = 10
    context_obj = Context(text, nr_cuvinte) 
    lista_cuvinte = context_obj.lista_cuvinte
    print lista_cuvinte
    print 'Programul a fost executat in %s secunde' %(str(time.time() - inceput))
