from __future__ import annotations
from . import command
from glom import glom, PathAccessError, T
import html
import requests
from typing import Dict, Any, Sequence, TYPE_CHECKING, List
import telegram as tg

if TYPE_CHECKING:
    from main import Bea, Command

headers = {
    'Referer': 'https://woordenlijst.org/'
}

SEARCH_ENDPOINT = 'https://woordenlijst.org/api-proxy'

# taken from JS from the woordenlijst website
type_map = {
        "COLL": "verb.",
        "AA": "bnw.",
        "ADV": "bw.",
        "ADP": "voorz.",
        "ART": "lidw.",
        "CONJ": "voegw.",
        "INT": "tussenw.",
        "RES": "",
        "NOU-C": "znw.",
        "NOU-P": "naam",
        "NUM": "telw.",
        "VRB": "werkw.",
        "PD": "vnw."
}

# but types can be more complex than this. There's a whole function I deobfuscated (thanks minification!)
# not implemented here yet though.

def get_type(match: Dict[str, Any]) -> str:
    ty = glom(match, 'gram.pos')
    subtyArt = glom(match, 'gram.subtypeArt', default=None)
    subty = glom(match, 'gram.subtype', default=None)
    gramty = glom(match, 'gram.type', default=None)
    scheidbaar = glom(match, 'gram.sep', default=None)

    basic_type = type_map.get(ty, "unknown")

    if (gramty == 'language'):
        return 'taalnaam'
    elif (gramty == 'ord'):
        return 'rangtelwoord'
    elif (gramty == 'card'):
        return 'hoofdtelwoord'
    elif (subty == 'fraction'):
        return 'breuk'
    elif (gramty == 'pron'):
        return 'vnw.' + basic_type
    elif (subtyArt == 'def'):
        return 'bep. ' + basic_type
    elif (subtyArt == 'indef'):
        return 'onbep. ' + basic_type
    elif (gramty == 'int'):
        return 'vragend ' + basic_type
    elif (gramty == 'recip'):
        return 'wederk. ' + basic_type
    elif (gramty == 'refl'):
        return 'reflexief ' + basic_type
    elif (gramty == 'poss'):
        return 'bez.' + basic_type
    elif (gramty == 'rel'):
        return 'betr. ' + basic_type
    elif (gramty == 'dem'):
        return 'aanw. ' + basic_type
    elif (gramty == 'pers'):
        return 'pers. ' + basic_type
    elif (scheidbaar == 'yes'):
        return 'scheidbaar ' + basic_type

    return basic_type

def woordenlijst_output(match: Dict[str, Any]) -> str:
    ty = glom(match, 'gram.pos')

    printable_ty = get_type(match)

    if (ty == 'NOU-C' or ty == 'NOU-P'):
        # noun
        gender = glom(match, 'gram.gender').replace('f', 'v')
        return f"<i>{printable_ty}</i> <b>{glom(match, 'gram.art')}</b> {glom(match, 'lemma')} (<i>{gender}</i>)"
    else:
        return f"<i>{printable_ty}</i> {glom(match, 'lemma')}"

def woordenlijst_request(word: str) -> requests.Response:
    return requests.get(SEARCH_ENDPOINT, params={'m': 'search', 'searchValue': word, 'tactical': 'true'}, headers=headers)

@command("(?:wl|woordenlijst) ((?:\w+ )*\w+)", pass_groups=True)
def woordenlijst(bea: Bea, bot: tg.Bot, update: tg.Update, groups: Sequence[str]) -> None:
    """ Look up a word in the Dutch word list. """
    woord = groups[0]

    try:
        resp = woordenlijst_request(woord)
    except requests.exceptions.ConnectionError:
        bea.reply(f'Sorry, ik kon de woordenlijst niet bereiken.')
        return

    if (resp.status_code != 200):
        bea.reply(f'Sorry, ik kon de woordenlijst niet bereiken. (HTTP-statuscode: {resp.status_code})')
        return

    data = resp.json()

    output = ""
    try:
        exact_matches = glom(data, '_embedded.exact')

        if (not exact_matches):
            output = "Spelling niet gevonden."
            suggestions = glom(data, '_embedded.suggestions')

            if (suggestions):
                suggestions = [f"{glom(match, 'lemma')} (<i>{glom(match, ('gram.pos', type_map.get(T, T)))}</i>)" for match in suggestions]
                output += (" Suggesties: " + ', '.join(suggestions))
        else:
            for match in exact_matches:
                output += woordenlijst_output(match) + "\n"
    except PathAccessError as e:
        if isinstance(e.exc, KeyError) and e.exc.args[0] == 'suggestions':
            pass
        else:
            output = f"Fout bij het verwerken van de data uit de woordenlijst. Diagnostische informatie: {e.get_message()}"

    output = output.strip()
    bea.reply(output, parse_mode='HTML', quote=False)



def init(bea: Bea, _: Any) -> List[Command]:
    return [woordenlijst]
