from os import path as px
from json import load
from flask_oidc import session
from re import split as rsplit
from unidecode import unidecode
from difflib import SequenceMatcher
from unicodedata import normalize, combining
from multiprocessing import cpu_count
from multiprocessing.dummy import Pool as ThreadPool

cpus = cpu_count()
pool = ThreadPool(cpus)


def remove_accents(input_str):
    nfkd_form = normalize('NFKD', input_str.strip())
    return u"".join([c for c in nfkd_form if not combining(c)])

def translit(x, invert=False):

    mapping = {
    'Љ': 'Lj',
    'Њ': 'Nj',
    'Џ': 'Dž',
    'А': 'A',
    'Б': 'B',
    'В': 'V',
    'Г': 'G',
    'Д': 'D',
    'Ђ': 'Đ',
    'Е': 'E',
    'Ж': 'Ž',
    'З': 'Z',
    'И': 'I',
    'Ј': 'J',
    'К': 'K',
    'Л': 'L',
    'М': 'M',
    'Н': 'N',
    'О': 'O',
    'П': 'P',
    'Р': 'R',
    'С': 'S',
    'Т': 'T',
    'Ћ': 'Ć',
    'У': 'U',
    'Ф': 'F',
    'Х': 'H',
    'Ц': 'C',
    'Ч': 'Č',
    'Ш': 'Š',
    'љ': 'lj',
    'њ': 'nj',
    'џ': 'dž',
    'а': 'a',
    'б': 'b',
    'в': 'v',
    'г': 'g',
    'д': 'd',
    'ђ': 'đ',
    'е': 'e',
    'ж': 'ž',
    'з': 'z',
    'и': 'i',
    'ј': 'j',
    'к': 'k',
    'л': 'l',
    'м': 'm',
    'н': 'n',
    'о': 'o',
    'п': 'p',
    'р': 'r',
    'с': 's',
    'т': 't',
    'ћ': 'ć',
    'у': 'u',
    'ф': 'f',
    'х': 'h',
    'ц': 'c',
    'ч': 'č',
    'ш': 'š'
    }
    if invert:
        mapping = {v: k for k, v in mapping.items()}  
    for key in mapping.keys():
        x = (x.replace(key, mapping[key]))
    return x

def base_form(x):
    x = remove_accents(x)
    x = translit(x)
    return x

def atoi(text):
    return int(text) if text.isdigit() else text

def natural_keys(text):
    return [ atoi(c) for c in rsplit(r'(\d+)', text) ]

def natsort(a):
    a.sort(key=natural_keys)
    return a


with open(px.join(px.dirname(__file__), "config.json"), "r", encoding="utf-8") as cf:
    cfg = load(cf)
    defi = cfg["definitions"]
    exi = cfg["examples"]
    expi = cfg["expressions"]
    conni = cfg["connections"]
    nots = cfg["notes"]

connroles = "('" + "', '".join(conni.keys()) + "')"
exproles = "('" + "', '".join(expi.keys()) + "')"



serbian_order = 'абвгдђежзијклљмнњопрстћуфхцчџш'
order_map = {char: i for i, char in enumerate(serbian_order)}

def serbian_sort_key(word):
    try:
        return [order_map.get(c.lower(), 999) for c in word]
    except:
        print(word)
        return [0]
    
def get_username():
    try: 
        uname = session["oidc_auth_profile"].get('email')
    except:
        uname = cfg["defaut_user"]  
    return uname

def user_can_dump():
    uname = get_username()
    if uname in cfg["dump_users"]:
        return True
    return False

def user_can_del():
    uname = get_username()
    if uname in cfg["del_users"]:
        return True
    return False

def users_role(uname):
    try:
        role = cfg["users"][uname]
    except:
        role = "guest"
    return role

def userrole():
    uname = get_username()
    role = users_role(uname)
    return uname, role

def verify_api_key(key):
    if key in cfg["api_keys"]:
        return True
    return False


def islike(x, y, ratio = 0.75):
    return SequenceMatcher(None, unidecode(x), unidecode(y)).ratio() > ratio

def islikein(x, a):
    for y in a:
        if islike(x, y):
            return True
    return False

def idem(x, y):
   return unidecode(x) == unidecode(y)

def idemin(x, a):
    for y in a:
        if idem(x, y):
            return True
    return False

def overlap(a, b):
    for x in a:
        for y in b:
            if idem(x, y):
                return True
    return False   

def startsw(x, y):
    return unidecode(y).startswith(unidecode(x))

def endsw(x, y):
    return unidecode(y).endswith(unidecode(x))

def isin(x, y):
    return unidecode(x) in unidecode(y)

def startswin(x, a):
    for y in a:
        if startsw(x, y):
            return True
    return False

def endswin(x, a):
    for y in a:
        if endsw(x, y):
            return True
    return False

def isinin(x, a):
    for y in a:
        if isin(x, y):
            return True
    return False