# coding: utf8
from gluon import *
from gluon.custom_import import track_changes; track_changes(True)

class LocationEngine:
    class tables:
        Countries = 'countries'
        Provinces = 'provinces'
        Cities    = 'cities'
        States    = 'state'
    
    def __init__(self, db, mail, tables = [], migrate=True, fake_migrate=False):
        self.db = db
        
        self.request = current.request
        self.session = current.session
        self.auth = current.session.auth
        self.T = current.T
        self.mail = mail
        
        self.define_tables(tables, migrate, fake_migrate)
    
    def get_all_countries_options(self):
        return [OPTION(country.name,_value=country.id) for country in self.db().select(self.db.countries.ALL)]
    
    def get_provinces_by_country_options(self, selected_country):
        return [OPTION(province.name, _value=province.id) for province in self.db(self.db.provinces.country == int(selected_country)).select()]
    
    def get_cities_by_province_options(self, selected_province):
        return [OPTION(city.name, _value=city.id) for city in self.db(self.db.cities.province == int(selected_province)).select()]
    
    def get_location_ids_from_settings(self, settings):
        from youadAPI.adviewer_api import AdViewerEngine
        selected_country = settings[AdViewerEngine.location]['country']
        selected_province = settings[AdViewerEngine.location]['province']
        selected_city = settings[AdViewerEngine.location]['city']
        db = self.db
        try:
            selected_country = int(selected_country)
            selected_province = int(selected_province)
            selected_city = int(selected_city)
        except ValueError:
            country = db(db.countries.name == selected_country).select().first()
            if country:
                selected_country = country.id
            else:
                selected_country = 0
            
            province = db(db.state.id == int(user_account.province)).select().first()
            if province:
                real_province = db(db.provinces.name == province.province).select().first()
                if real_province:
                    selected_province = real_province.id
                else:
                    selected_province = province.id
            else:
                selected_province = 0
            
            city = db(db.cities.name == selected_city).select().first()
            if city:
                selected_city = city.id
            else:
                selected_city = 0
                
        return selected_country, selected_province, selected_city
    
    def get_location_ids_from_useraccount(self, user_account):
        selected_country = user_account.country
        selected_province = user_account.province
        selected_city = user_account.city
        
        try:
            selected_country = int(selected_country)
            selected_province = int(selected_province)
            selected_city = int(selected_city)
        except ValueError:
            country = db(db.countries.name == selected_country).select().first()
            if country:
                selected_country = country.id
            else:
                selected_country = 0
            
            province = db(db.state.id == int(user_account.province)).select().first()
            if province:
                real_province = db(db.provinces.name == province.province).select().first()
                if real_province:
                    selected_province = real_province.id
                else:
                    selected_province = province.id
            else:
                selected_province = 0
            
            city = db(db.cities.name == selected_city).select().first()
            if city:
                selected_city = city.id
            else:
                selected_city = 0  
        
        return selected_country, selected_province, selected_city
    
    def get_location_options(self, selected_country, selected_province, selected_city):
        countries_options = self.get_all_countries_options()
        if "country" in self.request.vars:
            selected_country = self.request.vars['country']
            
            if "province_state" in self.request.vars:
                selected_province = self.request.vars['province_state']
                provinces_options = self.get_provinces_by_country_options(selected_country)
                
                if "city" in self.request.vars:
                    selected_city = self.request.vars['city']
                    cities_options = self.get_cities_by_province_options(selected_province)
                else:
                    cities_options = []
            else:
                cities_options = []
                provinces_options = []
        else:
            provinces_options = self.get_provinces_by_country_options(selected_country)
            cities_options = self.get_cities_by_province_options(selected_province)
        
        return countries_options, selected_country, provinces_options, selected_province, cities_options, selected_city
    
    def get_location(self, user_account):
        db = self.db
        try:
            country_id = int(user_account.country)
            country = db(db.countries.id == country_id).select().first()
            if country:
                country = country.name
            else:
                country = user_account.country
            
            province_id = int(user_account.province)
            province = db(db.provinces.id == province_id).select().first()
            if province:
                province = province.name
            else:
                province = user_account.province
            
            city_id = int(user_account.city)
            city = db(db.cities.id == city_id).select().first()
            if city:
                city = city.name
            else:
                city = user_account.city
        except:
            country = user_account.country
            province = db(db.state.id == int(user_account.province)).select().first()
            if province:
                province = province.province
            else:
                province = user_account.province
            city = user_account.city
        
        return dict(country = country, province = province, city = city)
    
    def define_tables(self, tables = [], migrate=True, fake_migrate=False):
        db = self.db
        if (not tables or tables and LocationEngine.tables.Countries in tables) and LocationEngine.tables.Countries not in db.tables:
            db.define_table(
                LocationEngine.tables.Countries,
                Field('name'),
                migrate=migrate,
                fake_migrate=fake_migrate
            )
        if (not tables or tables and LocationEngine.tables.Provinces in tables) and LocationEngine.tables.Provinces not in db.tables:
            db.define_table(
                LocationEngine.tables.Provinces,
                Field('country', db.countries, requires=IS_IN_DB(db, db.countries.id, '%(name)s')),
                Field('name'),
                migrate=migrate,
                fake_migrate=fake_migrate
            )
        if (not tables or tables and LocationEngine.tables.Cities in tables) and LocationEngine.tables.Cities not in db.tables:
            db.define_table(
                LocationEngine.tables.Cities,
                Field('country', db.countries, requires=IS_IN_DB(db, db.countries.id, '%(name)s')),
                Field('province', db.provinces, requires=IS_IN_DB(db, db.provinces.id, '%(name)s')),
                Field('name'),
                migrate=migrate,
                fake_migrate=fake_migrate
            )
        if (not tables or tables and LocationEngine.tables.States in tables) and LocationEngine.tables.States not in db.tables:
            # required to handle backward compatibility. 
            db.define_table(
                LocationEngine.tables.States, 
                Field('country'),
                Field('province'),
                migrate=migrate,
                fake_migrate=fake_migrate
            )
        