#view-uri pentru RSS si XML
# Create your views here.
import time
from datetime import datetime
import operator
import math
from hashlib import sha224 
from django.http import HttpResponse, HttpResponseRedirect, Http404
from django.shortcuts import render_to_response, get_object_or_404
from django.template import loader, Context
from django.core.cache import cache

from news.local.models import Snippet
from news.stiri.models import Categorie, Articol, CategoriePers, Ziar
from django.conf import settings
from news.engine.compute_poisson import LoadPoisson
from news.engine.create_clusters import LoadClusters
from news.engine.search import SearchClusters
from news.engine.functions import list_intersection
from news.utils import get_news_logger, clean_text
from news.stiri.utils import datetime_to_unixtime, unixtime_to_datetime
from news.stiri.utils import bold_articol, get_cluster_keys
from news.stiri.utils import get_articole_from_ids
from news.stiri.views import order_clusters, get_timp_parsare
from news.engine.context import Context as MogContext
from news.local.viewsdir.config import *
from news.libs.urlparser import UrlParser
from news.libs.solr import * 
from news.geo_utils import *
from news.libs.urlparser import local_upconfig
import logging

from news.utils import htmlspecialchars, clean_and_safe

#clustere pe prima pagina si in paginile de categorii
clusters_per_page = 15
res_per_page = 10
lungime_snippet = 300

def snippet_solr(request, snippet_id):
    """View solr pentru snippet.
    """
    try:
        snippet = Snippet.objects.get(id__exact=snippet_id)
    except Snippet.DoesNotExist:
        raise Http404
    articol_local = snippet.articol_local
    articol_data = format_solr_date(articol_local.data)
    articol_local.ziar = Ziar.objects.get(pk=articol_local.ziar_id)
    
    dict_return = {'snippet': snippet, 'articol_data': articol_data,
                   'articol': articol_local, }
    response = HttpResponse(mimetype='text/xml')
    
    t = loader.get_template('local/solr_snippet.html')
    c = Context(dict_return)
    response.write(t.render(c)) 
    return response

def filters(request):
    """Afiseaza filtrele intr-un view XML.
    """
    url = request.GET.get('path', '')
    test = url

    config = local_upconfig
    params = UrlParser(url, config=config)
    params.parse()
    pv = params.get_dict()
    pc = params.get_pconf()
    fn = params.get_fnames()

    # termen(ii) de cautare
    q = pv['params']['search']['value']
    if q == pc['search']['default']:
        dq = ""
        #TO DO - pentru related search tb eliminat
        rsearches = []
    else:
        dq = q
        #TO DO - pentru related search tb eliminat
        rsearches = []

    # tip de view
    #numItems = ITEMS_PER_PAGE_LIST
    #numItemsFloat = ITEMS_PER_PAGE_LIST_FLOAT
    numItems = numItemsFloat = 100

    # procesam criteriile de selectie
    nq = q 
    if dq == "":
        fq = ""
    else:
        fq = """%s""" % (nq)
    test = pv
    for lname, limit in pv['facets'].iteritems():
        facet = pc[lname]['map']
        if pc[lname].has_key('showfh'):
            sfh = pc[lname]['showfh']
            if not sfh(pv):
                continue
        if pc[lname]['multi']:
            # avem mai multe valori
            for value in limit:
                if pc[lname]['values'].has_key(value['value']):
                    value = pc[lname]['values'][value['value']]['svalue']
                else:
                    value = value['value']
                if value[0] == '[':
                    l = "%s:%s" % (facet, value)
                else:
                    l = "%s:\"%s\"" % (facet, value)
                if fq == "":
                    fq = """%s""" % (l)
                else:
                    fq = """%s AND %s""" % (fq, l)
        else:
            # avem o singura valoare
            if pc[lname]['values'].has_key(limit['value']):
                limit = pc[lname]['values'][limit['value']]['svalue']
            else:
                limit = limit['value']
            if limit[0] == '[':
                l = "%s:%s" % (facet, limit)
            else:
                l = "%s:\"%s\"" % (facet, limit)
            if fq == "":
                fq = """%s""" % (l)
            else:
                fq = """%s AND %s""" % (fq, l)                
    if fq == "":
        fq = q
        if not fq:
            fq = "snippet_latitude:[* TO *]"
        else:
            fq = "%s AND snippet_latitude:[* TO *]" %(fq)
    else:
        fq = "%s AND snippet_latitude:[* TO *]" %(fq)

    solr = Solr(SOLR_URL)
    fq = fq.replace('__', '/')
    solr.setQuery(fq)
    if fq != "":
        pass

    for facet in pc:
        if pc[facet]['map'] != None and pc[facet]['group'] == "facets":
            if pc[facet].has_key('showfh'):
                sfh = pc[facet]['showfh']
                if not sfh(pv):
                    continue
          
            solr.addFacet(pc[facet]['map'])
      
            if len(pc[facet]['values']):
                for k in pc[facet]['values']:
                    solr.addFacetValue(pc[facet]['map'], pc[facet]['values'][k]['svalue'])

    solr.setFacetOption("mincount", "1")
    solr.setOption("fl", "*,score")
    solr.setOption("rows", numItems)
    solr.setOption("limit", numItems)
    #sortam dupa data articolului, in ordine descrescatoare
    solr.setOption("sort", "articol_data desc")    
    #test = solr.getUrl()

    cid = "%s:%s" % (CACHE_PREFIX, sha224(solr.getUrl()).hexdigest())

    data = cache.get(cid)
    if data == None:
        data = solr.query()

        # replace la facet-urile custom
        for facet in pc:
            f = pc[facet]
            if len(f['values']) and f['map'] != None:
                if data.has_key('facet_counts') and data['facet_counts'].has_key('facet_fields') and data['facet_counts']['facet_fields'].has_key(f['map']) and len(data['facet_counts']['facet_fields'][f['map']]):
                    data['facet_counts']['facet_fields'][f['map']] = {}
                    for k in f['values']:
                        query = "%s:%s" % (f['map'], f['values'][k]['svalue'])
                        for fq, fqv in data['facet_counts']['facet_queries'].iteritems():
                            if fq == query and fqv:
                                data['facet_counts']['facet_fields'][f['map']][f['values'][k]['dvalue']] = fqv   

        numFound = data['response']['numFound']

        #pentru extinderea rezultatelor
        data['removeLimits'] = []
        bparams = params.build_get_sorted(False)
        for param in bparams:
            label = param['dvalue']
            url = params.build_url(param['param'], param['value'], 'd', url='')
            data['removeLimits'].append({'label': label, 'url': url})

        # facets
        data['facets'] = []
        if data.has_key('facet_counts') and data['facet_counts'].has_key('facet_fields'):
            for facet in data['facet_counts']['facet_fields']:
                f = {}
                f['o'] = pc[fn[facet]['pname']]['weight']
                f['name'] = fn[facet]['dname']
                f['code'] = facet
                f['items'] = []
                for item, icount in data['facet_counts']['facet_fields'][facet].iteritems():
                    ival = item
                    if pc[fn[facet]['pname']]['values'] != None:
                        for vname, vdata in pc[fn[facet]['pname']]['values'].iteritems():
                            if vdata['dvalue'] == item:
                                ival = vname

                    if (fn[facet]['pname'] == 'tag'):
                        extra_params = {'and_filter': True, 'url': ''}
                    else:
                        extra_params = {'url': ''}
                    url = params.build_url(fn[facet]['pname'], ival.replace('/', '__'), **extra_params)
                    #XXX - mihai - Cand avem un singur filtru scoatem conditia icount != numFound
                    #if icount > 0 and icount != numFound:
                    if icount > 0:
                        f['items'].append({'name': item, 'count': icount, 'url': url})

                if pc[fn[facet]['pname']].has_key('sortv') and not pc[fn[facet]['pname']]['sortv']:
                    pass
                else:
                    f['items'].sort(lambda x,y: cmp(x['count'], y['count']))
                    f['items'].reverse()
                f['sitems'] = f['items'][:MAX_FACET_TERMS_BASIC]
                if len(f['items']) > MAX_FACET_TERMS_BASIC:
                    f['hitems'] = f['items'][MAX_FACET_TERMS_BASIC:MAX_FACET_TERMS_BASIC + MAX_FACET_TERMS_EXPANDED]
                    f['has_more'] = 1
                if len(f['items']):
                    data['facets'].append(f)

        data['facets'].sort(cmp=lambda x,y: x['o']-y['o'])
        #test = data['facets'][0][]

    bounds = getBoundsFromData(data)
    dict_return = {'test': test, 'data': data, 'bounds': bounds}
    response = HttpResponse(mimetype='text/xml')
    #response = HttpResponse(mimetype='text/html')
    t = loader.get_template('local/filtre.html')
    c = Context(dict_return)
    response.write(t.render(c)) 
    return response 

def results(request):
    """Afiseaza rezultatele intr-un view XML.
    """
    latitude = get_float_or_404(request.GET.get('latitude', ''))
    longitude = get_float_or_404(request.GET.get('longitude', ''))
    radius = get_float_or_404(request.GET.get('radius', ''))
    proximity_query = get_proximity_query(latitude, longitude, radius)
    url = request.GET.get('path', '')

    #config1 = __import__('local_upconfig', globals(), locals(), [])
    config = local_upconfig
    params = UrlParser(url, config=config)
    params.parse()
    pv = params.get_dict()
    pc = params.get_pconf()
    fn = params.get_fnames()

    # termen(ii) de cautare
    q = pv['params']['search']['value']
    if q == pc['search']['default']:
        dq = ""
        #TO DO - pentru related search tb eliminat
        rsearches = []
    else:
        dq = q
        #TO DO - pentru related search tb eliminat
        rsearches = []

    # tip de view
    numItems = 100
    numItemsFloat = 100.0

    # procesam criteriile de selectie
    nq = q
    if dq == "":
        fq = ""
    else:
        fq = """%s""" % (nq)
    #adaugam proximity_query ca un criteriu de selectie
    if fq:
        fq += ' AND %s' % (proximity_query)
    else:
        fq = proximity_query
    for lname, limit in pv['facets'].iteritems():
        facet = pc[lname]['map']
        if pc[lname].has_key('showfh'):
            sfh = pc[lname]['showfh']
            if not sfh(pv):
                continue
        if pc[lname]['multi']:
            # avem mai multe valori
            for value in limit:
                if pc[lname]['values'].has_key(value['value']):
                    value = pc[lname]['values'][value['value']]['svalue']
                else:
                    value = value['value']
                if value[0] == '[':
                    l = "%s:%s" % (facet, value)
                else:
                    l = "%s:\"%s\"" % (facet, value)
                if fq == "":
                    fq = """%s""" % (l)
                else:
                    fq = """%s AND %s""" % (fq, l)
        else:
            # avem o singura valoare
            if pc[lname]['values'].has_key(limit['value']):
                limit = pc[lname]['values'][limit['value']]['svalue']
            else:
                limit = limit['value']
            if limit[0] == '[':
                l = "%s:%s" % (facet, limit)
            else:
                l = "%s:\"%s\"" % (facet, limit)
            if fq == "":
                fq = """%s""" % (l)
            else:
                fq = """%s AND %s""" % (fq, l)
    if fq == "":
        fq = q
        if not fq:
            fq = "snippet_latitude:[* TO *]"
        else:
            fq = "%s AND snippet_latitude:[* TO *]" %(fq)
    else:
        fq = "%s AND snippet_latitude:[* TO *]" %(fq)

    solr = Solr(SOLR_URL)
    fq = fq.replace('__', '/')
    solr.setQuery(fq)
    if fq != "":
        pass

    for facet in pc:
        if pc[facet]['map'] != None and pc[facet]['group'] == "facets":
            if pc[facet].has_key('showfh'):
                sfh = pc[facet]['showfh']
                if not sfh(pv):
                    continue
          
            solr.addFacet(pc[facet]['map'])
      
            if len(pc[facet]['values']):
                for k in pc[facet]['values']:
                    solr.addFacetValue(pc[facet]['map'], pc[facet]['values'][k]['svalue'])

    solr.setFacetOption("mincount", "1")
    solr.setOption("fl", "*,score")
    solr.setOption("rows", numItems)
    solr.setOption("limit", numItems)
    #sortam dupa numarul de victime, in ordine descrescatoare
    solr.setOption("sort", "articol_data desc")
    test = solr.getUrl()
    #test = fq

    cid = "%s:%s" % (CACHE_PREFIX, sha224(solr.getUrl()).hexdigest())

    data = cache.get(cid)
    if data == None:
        data = solr.query()
        numFound = data['response']['numFound']

    duplicates_dict = get_duplicates_dict(data['response']['docs'])
    for incident in data['response']['docs']:
        t = time.strptime(incident['articol_data'], "%Y-%m-%dT%H:%M:%SZ")
        incident['articol_data'] = time.strftime("%d/%m/%Y", t)
        incident['nr_duplicates'] = duplicates_dict.get(incident['snippet_id'], 0)

    dict_return = {'test': test, 'data': data, }
    response = HttpResponse(mimetype='text/xml')
    t = loader.get_template('local/results.html')
    c = Context(dict_return)
    response.write(t.render(c)) 
    return response

def get_duplicates_dict(incident_list):
    return_dict, temp_dict = {}, {}
    for incident in incident_list:
        dict_key = 'lat:%s-lon:%s' %(str(incident['snippet_latitude']), str(incident['snippet_longitude']))
        if not temp_dict.has_key(dict_key):
            temp_dict[dict_key] = [incident['snippet_id']]
        else:
            temp_dict[dict_key].append(incident['snippet_id'])
    for key, ids in temp_dict.iteritems():
        for incident_id in ids:
            return_dict[incident_id] = len(ids) - 1
    return return_dict

def get_float_or_404(text):
    try:
        value = float(text)
    except ValueError:
        return Http404
    else:
        return value

def get_proximity_query(latitude, longitude, radius):
    """Se da latitudine, longitudine si radius in kilometri.
    Se obtine limitele de Nord, Sud, Vest si Est in functie de parametrii de mai sus,
    si se construieste un query pt. Lucene de forma
    incident_longitude:[0 TO 10] AND incident_latitude:[20 TO 40]
    """
    add_lat = getKmPerLat() * radius
    add_long = getLonPerKmAtLat(latitude) * radius
    limita_nord = latitude + add_lat
    limita_sud = latitude - add_lat
    limita_est = longitude + add_long 
    limita_vest = longitude - add_long
    query = 'snippet_longitude: [%s TO %s] AND snippet_latitude: [%s TO %s]' % (str(limita_vest), str(limita_est),
                                                                                  str(limita_sud), str(limita_nord))
    return query
    

def format_solr_date(data):
    #formateaza o data sub forma '1995-12-31T23:59:59Z'
    return data.strftime("%Y-%m-%dT%H:%M:%SZ")

def getBoundsFromData(data):
    latitude_list = []
    longitude_list = []    
    for incident in data['response']['docs']:
        if incident.has_key('snippet_latitude'):
            latitude = incident['snippet_latitude']
            latitude_list.append(latitude)
        if incident.has_key('snippet_longitude'):
            longitude = incident['snippet_longitude']
            longitude_list.append(longitude)
    if latitude_list and longitude_list:
        max_latitude = max(latitude_list)
        min_latitude = min(latitude_list)
        max_longitude = max(longitude_list)
        min_longitude = min(longitude_list)
        north_east = {'latitude': max_latitude, 'longitude': max_longitude}
        south_west = {'latitude': min_latitude, 'longitude': min_longitude}
        return_dict = {'north_east': north_east, 'south_west': south_west, }
    else:
        return_dict = None
    return return_dict

