"""
Mongodb storage init 

- collections queries initialization

TODO : maybe put the mongodb connector into the flask app object
with the pymongo library.
"""
import urllib.parse

from pymongo import MongoClient

from .config import dbadmin, dbpassword, server_ip
from .helper import normalize_trigrams

# ______________________________________________________________________________
# database connexion

def database_connexion(username, password, server_ip):
    username = urllib.parse.quote_plus(dbadmin)
    password = urllib.parse.quote_plus(dbpassword)
    dbclient = MongoClient(f'mongodb://{username}:{password}@{server_ip}:27017')
    # database
    actesdb = dbclient["actesdb"]
    return actesdb

actesdb = database_connexion(dbadmin, dbpassword, server_ip)
# collections
housecol = actesdb["house"]
# the acte collection is the most important collection
actecol = actesdb["acte"]
helpers = actesdb["helpers"]
#folium_map = actesdb["folium_map"]

# ______________________________________________________________________________
# storage extractor utilities

def make_acteid_from_route(house=None, prince=None, date_and_item=None):
    "/acte/Anjou/Isabelle_i/1441_08_05a -> anj_isa_i_1441_08_05a"
    return "_".join([trigram_house(house), bigram_prince(prince), date_and_item])


def extract_princes_in_houses():
    """Extracts all princes from a house
    by queries in the storage, (not by using csv metadatas)

    sample:
    >>> extract_princes_in_houses['anjou']
    [{'prince_name': "Louis Ier d'Anjou", 'prince_code': 'lo_i'}, {'prince_name': "Louis III d'Anjou", 'prince_code': 'lo_iii'}, {'prince_name': 'Isabelle de Lorraine', 'prince_code': 'isa_i'}, {'prince_name': "Louis II d'Anjou", 'prince_code': 'lo_ii'}, {'prince_name': 'Marie de Blois', 'prince_code': 'mar_i'}, {'prince_name': "René d'Anjou", 'prince_code': 're_i'}, {'prince_name': "Yollande d'Aragon", 'prince_code': 'yol_i'}]
    """
    princes_in_houses = dict()
    for house in housecol.find():
        housename = house['name'].lower()
        query = list(actecol.aggregate([{
            "$match": {"house": housename}}, 
            {'$group': {'_id': {'prince_name': '$prince_name', 'prince_code': '$prince_code'}}
            }]))
        princes_in_houses[housename] = [pr['_id'] for pr in query]
    return princes_in_houses

def extract_prince_in_house(house, prince_code):
    """
    :param house: sample: 'bourbon'
    :param prince_code: sample: 'lo_i'
    
    :result: sample: {'prince_name': "Louis Ier d'Anjou", 'prince_code': 'lo_i'}
    
    """
    princes_in_houses = extract_princes_in_houses()
    princes_in_house = princes_in_houses[house]
    for pr in princes_in_house:
        if pr['prince_code'] == prince_code:
            return pr


# ______________________________________________________________________________
# in memory storage extracted 'meta' informations upon the database
# TODO: if it takes too much time at launch, put it in something like
# a `flask init` procedure

helpers_dicts = helpers.find_one()
house_trigram = helpers_dicts["house_trigram"]
prince_bigram = helpers_dicts["prince_bigram"]
princes_in_houses = extract_princes_in_houses()

"""
house_trigram sample:
{'Alencon': 'alb', 'Anjou': 'anj', 'Armagnac': 'arm', 'Bourbon': 'brb', 'Bretagne': 'bre', 'Bourgogne': 'brg', 'Berry': 'bry', 'Orleans': 'orl', 'Savoie': 'sav'}
"""
house_trigram = normalize_trigrams(house_trigram)
"""
prince_bigram sample: 
{'Agnes': 'agn', 'Alain': 'al', 'Amedee': 'am', 'Anne': 'ann', 'Arthur': 'ar', 'Bernard': 'be', 'Beatrice': 'bea', 'Blanche': 'bla', 'Bonne': 'bon', 'Catherine': 'cat', 'Charles': 'ch', 'Edouard': 'ed', 'Francois': 'fr', 'Francoise': 'fra', 'Jean': 'je', 'Jeanne': 'jea', 'Louis': 'lo', 'Marguerite': 'mag', 'Marie': 'mar', 'Philippe': 'ph', 'Pierre': 'pi', 'Rene': 're', 'Isabelle': 'isa', 'Yolande': 'yol'}
"""
prince_bigram = normalize_trigrams(prince_bigram)


def inverted_prince_bigram(bigram):
    "Translates  ch -> Charles"
    inverted_prince_bigram = {value: key for key, value in prince_bigram.items()}
    return inverted_prince_bigram[bigram]


def bigram_prince(prince):
    "Translates Charles_i -> ch_i"
    name, number = prince.split("_")
    return prince_bigram[name] + "_" + number


def trigram_house(house):
    return house_trigram[house]





