import asyncio
import os

from aiohttp import web

from dict_checker import DictChecker
from es_predict import es_predict
from hypernymus import Hypernymus
from specs_checker import SpecSChecker
from spell_checker import SpellChecker
from stemmer import Stemmer
from thesaurus import Thesaurus


async def handle(request, callback, *args, **kwargs):
    arg_values = [request.match_info.get(arg_name, None) for arg_name in args]
    kwarg_values = {arg_key: request.match_info.get(arg_name, None) for arg_key, arg_name in kwargs.items()}

    if (args and all(arg_values)) or (kwargs and all(kwarg_values.items())):
        try:
            result = callback(*arg_values, **kwarg_values)
        except Exception as e:
            result = "Internal error: unhandled exception {}".format(e)
    else:
        result = "Error: not all parameters presented"

    return web.json_response({"result": result})


if __name__ == '__main__':
    thesaurus = Thesaurus(os.environ["W2V_PATH"])
    hypernymus = Hypernymus(os.environ["HYPERNYMS_PATH"])
    spell_checker = SpellChecker(os.environ["EXCLUSION_WORDS_PATH"], ru="ru_RU")
    dict_checker = DictChecker(os.environ["EXCLUSION_WORDS_PATH"], ru="ru_RU")
    specs_checker = SpecSChecker()
    stemmer = Stemmer()
    es_url = os.environ["ELASTICSEARCH_URL"]

    handlers = [
        ("/get_most_similar/{text}",
         lambda request: handle(request, thesaurus.most_similar, words="text")),
        ("/get_hypernyms/{text}",
         lambda request: handle(request, hypernymus.hypernym, words="text")),
        ("/spell_check/{dict_key}/{text}",
         lambda request: handle(request, spell_checker.check_text, text="text", dict_key="dict_key")),
        ("/dict_check/{dict_key}/{text}",
         lambda request: handle(request, dict_checker.check_text, text="text", dict_key="dict_key")),
        ("/specs_check/{text}",
         lambda request: handle(request, specs_checker.check_text, text="text")),
        ("/analyze_text/{text}",
         lambda request: handle(request, stemmer.analyze, text="text")),
        ("/lemmatize_text/{text}",
         lambda request: handle(request, stemmer.lemmatize, text="text")),
        ("/predict_query/{query}",
         lambda request: handle(request, lambda keywords: es_predict(es_url, keywords), keywords="query"))
    ]

    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)

    app = web.Application()

    for url, handler in handlers:
        app.router.add_get(url, handler)

    web.run_app(app, host="0.0.0.0", loop=loop)
