#script pentru updatarea training-ului categoriilor
import os
import sys
import math
import time
import datetime
import marshal
from sets import Set
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.create_clusters import LoadClusters
from news.engine.context import Context as MogContext
from news.utils import get_news_logger
from news.stiri.utils import datetime_to_unixtime

class Training(object):
    """Clasa pentru crearea unei liste de training, pentru obtinerea listei de training etc.
       O categorie este deginita de mai multi itemi-categorii, un dictionar de forma
       {'data_unixtime': 12131212, 'lista_cuvinte': ['geoana', 'psd', 'arad', 'flutur',
       'ungureanu', 'lui', 'nitulescu', 'dae', 'ion', 'ministr'], 'id_categorie': '2'},
       ce arata ca categoria cu ID-ul '2' este definita de lista de cuvinte lista_cuvinte,
       calculata pe baza unui articol ce a fost creat la 'data_unixtime'.
       In lista de training trebuie sa avem cel putin MIN_TRAINING_ARTICLES si cel mult
       MAX_TRAINING_ARTICLES dintr-o anumita categorie.
       Daca based_on == 'articole' (default), atunci vom calcula lista de training pe baza
       articolelor din baza de date, altfel vom calcula lista pe baza clusterelor care deja
       au fost alocate unor anumite categorii (mai ales pentru cazul in care updatam lista
       de training in fiecare zi, pentru a o tine la zi).
    """

    def __init__(self, based_on='clusters'):
        self.based_on = based_on
        self.new_categ_items = self.get_new_categ_items(self.based_on)
        self.old_categ_items = self.get_old_categ_items()
        self.merged_items = self.merge_categ_items(self.old_categ_items, self.new_categ_items)
        #salvam categ-items obtinute
        self.saver = SaveTraining(self.merged_items)

    def get_new_categ_items(self, based_on):
        #obtine item-categorii bazandu-se fie pa articolele deja existente in baza de date
        #fie pe clusterele deja impartite pe categorii
        lista_return = []
        if based_on == 'articole':
            articole = articols.exclude(categorie__alias='fara_categorie')
            for iter, articol in enumerate(articole):
                if articol.text:
                    context_obj = MogContext(articol.text, 10)
                    id_categorie = articol.get_categorie().id
                    lista_cuvinte = context_obj.get_important_kws(context_obj.cuvinte_context)
                    categ_item = {'id_categorie': id_categorie, 'lista_cuvinte': lista_cuvinte,
                                  'data': datetime_to_unixtime(articol.data), }
                    lista_return.append(categ_item)
        else:
            #pentru cazul in care cream trainingul pe baza clusterelor deja impartite pe categorii
            #obtinem clusterele care au deja categoriile setate
            cluster_loader = LoadClusters()
            lista_clustere = [cluster for cluster in cluster_loader.lista_clustere if cluster['categorie'] != 0]
            for cluster in lista_clustere:
                lista_cuvinte = [item[1] for item in cluster['lista_cuvinte']]                
                categ_item = {'id_categorie': cluster['categorie'], 'lista_cuvinte': lista_cuvinte,
                              'data': cluster['data']}
                lista_return.append(categ_item)
        return lista_return

    def get_old_categ_items(self):
        #obtine categ-item-urile deja salvate
        loader = LoadTraining()
        return loader.lista_training

    def merge_categ_items(self, old_items, new_items):
        #se dau 2 lista de categ_items; se calculeaza una noua
        #pa baza celor 2, pastrand cele mai noi MAX_TRAINING_ARTICLES
        #articole din fiecare categorie
        merged_items, temp_items = [], []
        dict_temp, dict_categorii = {}, {}
        temp_items = old_items
        temp_items.extend(new_items)
        for item in temp_items:
            dict_temp[self.categ_item_to_string(item)] = item
        temp_merged_items = dict_temp.values()
        for item in temp_merged_items:
            if dict_categorii.has_key(item['id_categorie']):
                dict_categorii[item['id_categorie']].append(item)
            else:
                dict_categorii[item['id_categorie']] = [item]
        #pastram cel mult MAX_TRAINING_ARTICLES din fiecare categorie
        for key, values in dict_categorii.iteritems():
            lista_temp = [[item['data'], item] for item in values]
            lista_temp.sort()
            lista_temp.reverse()
            lista_temp = [item[1] for item in lista_temp]
            lista_temp = lista_temp[:settings.MAX_TRAINING_ARTICLES]
            merged_items.extend(lista_temp)
        return merged_items

    def categ_item_to_string(self, categ_item):
        #se daun categ_item de forma {'lista_cuvinte': ['lei', 'sugestii', 'municipa', 'informativ',
        #'corporative', 'corectitudine', 'articole', 'recomandari', 'obligatiuni', 'certificate'],
        #'data': 1158565735.0, 'id_categorie': 3} si se transforma intr-un string
        cuvinte = '_'.join(categ_item['lista_cuvinte'])
        return '%d_%s_%s' %(categ_item['id_categorie'], cuvinte, str(categ_item['data']))
            
class SaveTraining:
    """Salveaza lista de training""" 
    
    def __init__(self, lista_training):
        self.lista_training = lista_training
        self.root = settings.ENGINE_ROOT
        try:
            self.file = open(self.root + 'files/lista_training.txt', 'w+')
        except IOError:
            print 'Nu am putut deschide fisierul %sfiles/lista_training.txt' %(self.root)
        else:
            self.salveaza_training(self.lista_training)
            self.file.close()
            
    def salveaza_training(self, lista_training):
        self.file.truncate(0)
        marshal.dump(lista_training, self.file)

class LoadTraining:
    """Clasa ce incarca lista de training"""
    
    def __init__(self):
        self.root = settings.ENGINE_ROOT
        try:
            self.file = open(self.root + 'files/lista_training.txt', 'r+')
        except IOError:
            print 'Nu am putut deschide fisierul %sfiles/lista_training.txt' %(self.root)
        else:
            self.lista_training = self.get_lista_training()
            self.file.close()

    def get_lista_training(self):
        return marshal.load(self.file)

if __name__ == '__main__':
    inceput = time.time()
    trainer = Training()
    #loader = LoadTraining()
    #print len(loader.lista_training)
    """for item in loader.lista_training:
        print item.get('lista_cuvinte', 'Nu exista')"""
    #lista_temp = [item for item in loader.lista_training if item.get('lista_cuvinte')]
    #print len(lista_temp)
    print 'Programul a fost executat in %s secunde' %(str(time.time() - inceput))
