#parsere pentru ziares
import urllib
import sys
import re
import time
import os
import md5
from datetime 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, Categorie, Ziar
from news.utils import htmlspecialchars, encode_url, clean_text, clean_and_safe, safe_unicode
from news.utils import string_distance, safe_str

class ParseZiar(object):
    """Clasa pentru parsarea articolelor din ziare.
    """

    def __init__(self, ziar, use_string_diff=1):
        self.ziar, self.use_string_diff = ziar, use_string_diff        
        self.url, self.new_prima_pagina = self.ziar.main_link, ''
        self.ziar = self.clean_ziar_fields(self.ziar)
        #print self.ziar
        self.main_page_dict = self.get_main_page(self.url)
        if not self.use_string_diff:
            diff = 0
        else:
            diff = string_distance(safe_str(self.ziar.prima_pagina), self.new_prima_pagina)                    
        if diff <= settings.PRIME_PAGINI_SIMIL and self.main_page_dict:
            if self.ziar.are_categorii:
                self.linkuri_articole = self.get_categ_data(self.main_page_dict)
            else:
                self.linkuri_articole = self.main_page_dict.keys()
            self.articole = self.get_articole(self.linkuri_articole)
            #daca totul a fost ok salvam si prima pagina, fara codul html
            #ziar.prima_pagina = unicode(self.new_prima_pagina, 'latin-1').encode('utf-8')
            ziar.prima_pagina = self.new_prima_pagina
            ziar.save()
        else:
            self.articole = {}
            print 'Ziarul %s nu s-a schimbat semnificativ de la ultima parsare.' %(str(self.ziar))

    def clean_ziar_fields(self, ziar):
        """Schimba campurile de tip Char din unicode in str pentru un Ziar
        """
        char_field_names = [field.attname for field in ziar._meta.fields if field.get_internal_type() == 'CharField']
        for field_name in char_field_names:
            try:
                setattr(ziar, field_name, str(getattr(ziar, field_name)))
            except UnicodeEncodeError:
                continue
        return ziar

    def get_main_page(self, url):
        #obtine link-uri de pe prima pagina
        url_dict = {}
        categorie = self.ziar.nume
        inc_articol = 0
        try:
            text = self.open_url(url)
        except IOError:
            print 'Nu am putut deschide prima pagina %s' %(url)
        except AttributeError:
            print 'Nu am putut citi prima pagina %s' %(url)
        else:
            self.new_prima_pagina = clean_text(safe_unicode(text))
            if not self.ziar.main_limita_jos_link:
                main_limita_jos_link = len(text)
            else:                
                main_limita_jos_link = text.find(self.ziar.main_limita_jos_link)
            if self.ziar.main_add_current_link:
                url_dict[url] = categorie
            while inc_articol != -1:
                inc_articol = text.find(str(self.ziar.main_inc_articol), inc_articol + 1, main_limita_jos_link)
                if inc_articol != -1:
                    if self.ziar.main_link_rfind:
                        inc_link = text.rfind(self.ziar.main_inc_link, 0, inc_articol)
                    else:
                        inc_link = text.find(self.ziar.main_inc_link, inc_articol)
                    end_link = text.find(self.ziar.main_end_link, inc_link)
                    link = text[inc_link + int(self.ziar.main_len_link_first) * len(self.ziar.main_inc_link):end_link]
                    if not link.startswith(self.ziar.main_link_articol):
                        link = self.ziar.main_link_articol + link
                    link = htmlspecialchars(link.strip())
                    link = encode_url(link)
                    if self.ziar.lista_caractere:
                        link = self.strip_caractere(self.ziar.lista_caractere, link)
                    if '#' in link:
                        link = link[:link.find('#')]
                    if '">' in link:
                        link = link[:link.find('">')]
                    url_dict[link] = categorie
        return url_dict 

    def strip_caractere(self, lista_caractere, link):
        #se da o lista de caractere de forma ['"__'__;'']
        #de faca un split dupa __ pentru a obtine caracterele si a le elimina de
        #la sfarsitul linkului
        split_caractere = lista_caractere.split('__')
        for caracter in split_caractere:
            if link.endswith(caracter):
                return link[:-len(caracter)]
        return link

    def get_articole(self, linkuri_articole):
        #obtine datele pentru fiecare articole ce are link-ul in linkuri_articole
        dict_articole = {}
        print len(linkuri_articole)
        for j, link in enumerate(linkuri_articole):
            #print 'index = %d' %(j)
            try:
                text = self.open_url(link)
            #except IOError:
            except:
                print 'Eroare deschidere pagina %s' %(link)
                continue
            if self.ziar.find_inc_titlu:
                start_inc_titlu = text.find(self.ziar.find_inc_titlu)
            else:
                start_inc_titlu = 0
            inc_titlu = text.find(self.ziar.inc_titlu, start_inc_titlu)
            #daca nu gasesc titlul nu parsez articolul
            if inc_titlu == -1:
                print 'Nu am gasit titlu pentru %s' %(link)
                continue
            inc_titlu = text.find(self.ziar.lista_titlu_first, inc_titlu) + len(self.ziar.lista_titlu_first)
            end_titlu = text.find(self.ziar.lista_titlu_second, inc_titlu)
            titlu = clean_text(safe_unicode(text[inc_titlu:end_titlu]))
            #vezi http://www.reportlab.com/i18n/python_unicode_tutorial.html
            try:
                titlu = unicode(titlu, 'latin-1').encode('utf-8')
            except:
                pass
            inc_text = text.find(self.ziar.inc_text, inc_titlu + int(self.ziar.ofset_inc_text)) + int(self.ziar.post_len_inc_text) * len(self.ziar.inc_text)
            if self.ziar.text_return_first:
                text_return_first = text.find(self.ziar.text_return_first, inc_text) + int(self.ziar.len_text_return_first) * len(self.ziar.text_return_first)
            else:
                text_return_first = inc_text
            text_return_second = text.find(self.ziar.text_return_second, inc_text)
            corp_articol = clean_text(safe_unicode(text[text_return_first:text_return_second]))
            #print link
            #print titlu
            #print corp_articol
            #vezi http://www.reportlab.com/i18n/python_unicode_tutorial.html 
            try:
                corp_articol = unicode(corp_articol, 'latin-1').encode('utf-8')
            except:
                pass
            print 'Am procesat "%s - %s"' %(titlu, str(self.ziar))
            dict_articole[link] = {'titlu': titlu, 'corp': corp_articol, 'data': datetime.now()}
        return dict_articole
    
    def get_categ_data(self, url_dict):
        url_list = url_dict.keys()
        linkuri_return = []
        for url in url_list:
            try:
                text = self.open_url(url)
            except IOError:
                print 'Nu am putut deschide pagina categorie %s' %(url)
            else:
                if text:
                    inc_titlu = 0
                    if self.ziar.categ_add_current_link:
                        linkuri_return.append(url)
                    if self.ziar.categ_limita_jos and self.ziar.categ_limita_jos != -1:
                        categ_limita_jos = text.find(self.ziar.categ_limita_jos)
                    else:
                        categ_limita_jos = len(text)                    
                    while inc_titlu != -1:
                        inc_titlu = text.find(self.ziar.categ_inc_titlu, inc_titlu + 1, categ_limita_jos)
                        if inc_titlu != -1:
                            if self.ziar.categ_link_rfind:
                                categ_link_first = text.rfind(self.ziar.categ_link_first, 0, inc_titlu) + int(self.ziar.categ_len_link_first) * len(self.ziar.categ_link_first)
                            else:
                                categ_link_first = text.find(self.ziar.categ_link_first, inc_titlu) + int(self.ziar.categ_len_link_first) * len(self.ziar.categ_link_first)
                            categ_link_second = text.find(self.ziar.categ_link_second, categ_link_first + 1)
                            link = self.ziar.categ_link_ziar + text[categ_link_first:categ_link_second]
                            link = encode_url(link.strip().replace('&amp;', '&'))
                            if '#' in link:
                                link = link[:link.find('#')]
                            if link not in linkuri_return:
                                #verificam ca linkul curent este de pe site-ul ziarului
                                linkuri_return.append(link)
        return linkuri_return

    def open_url(self, url):
        #metoda pentru deschidere pagina
        f = urllib.urlopen(url)
        text = f.read()
        f.close()
        return text

class SaveArticole(object):
    """Clasa pentru salvarea articolelor dintr-un ziar
    articole[url_articol] = {'titlu': titlu, 'corp': corp_articol, 'data': data, }
    """
    
    def __init__(self, ziar, articole):
        self.ziar = ziar
        self.articole = articole
        self.fara_categorie = self.get_fara_categorie()
        self.salveaza_articole(self.ziar, self.articole)

    def get_fara_categorie(self):
        return Categorie.objects.get(alias__exact='fara_categorie')
        
    def salveaza_articole(self, ziar, articole):
        for url, articol in articole.iteritems():
            hash = md5.new(articol['titlu'] + url).hexdigest()
            try:
                art_obj = Articol.objects.get(hash__exact=hash)
            except Articol.DoesNotExist:
                art_obj = None
            except AssertionError:
                #avem deja doua sau mai articole cu acelasi url
                art_obj = 1
                print 'Exista doua sau mai multe articole cu url-ul %s' %(url)
            if art_obj is None:
                art_obj = Articol(titlu=articol['titlu'], link=url, ziar_id=ziar.id,
                                  categorie_id=self.fara_categorie.id, data=articol['data'],
                                  text=articol['corp'], status=1, 
                                  solr_changed=1)
                try:
                    art_obj.save()
                except:
                    print 'Nu am putut salva "%s - %s"' %(articol['titlu'], str(ziar))
                else:
                    #print 'Am salvat articolul "%s - %s"' %(articol['titlu'], str(ziar))
                    pass
    
if __name__ == "__main__":
    inceput = time.time()
    #query = {'parsare__exact': 1}
    query = {'nume__exact': 'Buna Ziua Iasi'}
    lista_ziare = Ziar.objects.filter(**query)
    for ziar in lista_ziare:
        parser = ParseZiar(ziar, use_string_diff=0)
        #SaveArticole(ziar, parser.articole)
    print 'Programul a fost executat in %s secunde' %(str(time.time() - inceput))        
