#-*- coding: utf-8 -*-
"""

@author:		Martí Congost
@contact:		marti.congost@whads.com
@organization:	Whads/Accent SL
@since:			September 2009
"""
import re
import sys
from time import time
from simplejson import loads
from urllib import urlopen
from cocktail.events import event_handler
from cocktail.translations import translations
from cocktail import schema
from cocktail.persistence import datastore
from woost.models import Extension, Language

translations.define("CountriesExtension",
    ca = u"Països",
    es = u"Países",
    en = u"Countries"
)

translations.define("CountriesExtension-plural",
    ca = u"Països",
    es = u"Países",
    en = u"Countries"
)

translations.define("CountriesExtension.update_frequency",
    ca = u"Freqüència d'actualització",
    es = u"Frecuencia de actualización",
    en = u"Update frequency"
)

translations.define("CountriesExtension.update_frequency-explanation",
    ca = u"El nombre de dies entre actualitzacions de la llista de paisos",
    es = u"El número de días entre actualizaciones de la lista de países",
    en = u"Number of days between updates to the country list"
)

SECONDS_IN_A_DAY = 60 * 60 * 24


class CountriesExtension(Extension):

    def __init__(self, **values):
        Extension.__init__(self, **values)
        self.extension_author = u"Whads/Accent SL"
        self.set("description",
            u"""Proporciona accés a la llista de països del món,
            actualitzada a través d'Internet.""",
            "ca"
        )
        self.set("description",            
            u"""Proporciona acceso a la lista de países del mundo, actualizada
            a través de Internet.""",
            "es"
        )
        self.set("description",
            u"""Provides a list of world countries, automatically updated from
            the Internet.""",
            "en"
        )

    last_update = None

    update_frequency = schema.Integer(
        min = 1,
        required = True,
        default = 15
    )

    @event_handler
    def handle_loading(cls, event):
        
        from woost.extensions.countries import country, strings

        now = time()
        ext = event.source
        
        if ext.last_update is None \
        or now - ext.last_update >= ext.update_frequency * SECONDS_IN_A_DAY:
            try:
                ext.update_country_list()
            except:
                pass
            else:
                ext.last_update = now
                datastore.commit()

    def update_country_list(self):
        from woost.extensions.countries.country import Country
        error = None
        
        database_modified = False
        service_uri = "http://www.lonelydrops.com/drops/1.0/list/%s/countries"
    
        data_expr = re.compile(
            r"var\s+drops_countries_[a-z]{2}\s*=\s*([^;]+)",
            re.DOTALL
        )
        json_property_normalization = re.compile(
            r"([a-zA-Z_$][a-zA-Z_$0-9]*)(?=\s*:)"
        )

        for language in Language.codes:
            try:
                javascript = urlopen(service_uri % language).read()
            except Exception, error:
                pass
            else:
                match = data_expr.search(javascript)

                if not match:
                    sys.stderr.write(
                        "The country list provider returned data in an "
                        "unexpected format (requested translation: %s)" % language
                    )
                    continue

                json = match.group(1)
                json = json_property_normalization.sub(r'"\1"', json)
                
                try:
                    data = loads(json)
                except Exception, error:
                    sys.stderr.write(
                        "The country list provider returned invalid data: %s"
                        "(requested translation: %s)\n" % (error, language)
                    )
                    continue

                for country_data in data:

                    # Ignore continents
                    if country_data.get("isParent"):
                        continue

                    name = country_data["label"]
                    iso_code = country_data["value"].lower()
                    country = Country.get_instance(iso_code = iso_code)

                    # New country
                    if country is None:
                        country = Country()
                        country.iso_code = iso_code
                        country.set("country_name", name, language)
                        country.insert()
                        database_modified = True

                    # Modified country
                    elif country.get("country_name", language) != name:
                        country.set("country_name", name, language)
                        database_modified = True
        
        if error:
            raise error

        return database_modified

