from functools import partial
from typing import Union, List, Tuple, Dict

import xlrd

from kss._utils.logger import logger
from kss._utils.multiprocessing import _run_job
from kss._utils.sanity_checks import _check_text, _check_num_workers

xlrd.xlsx.ensure_elementtree_imported(False, None)
xlrd.xlsx.Element_has_iter = True

from koparadigm import Paradigm, prettify

paradigm_obj = Paradigm()


def paradigm(
    text: Union[str, List[str], Tuple[str]],
    num_workers: Union[int, str] = "auto",
    verbose: bool = False,
) -> Union[Dict[str, str], List[Dict[str, str]]]:
    """
    This searches paradigms of the given text.

    Args:
        text (Union[str, List[str], Tuple[str]): single text or list of texts
        num_workers (Union[int, str]): the number of multiprocessing workers
        verbose (bool): whether to print the results or not

    Returns:
        Union[Dict[str, str], List[Dict[str, str]]]: paradigms of the given text

    Examples:
        >>> from kss import Kss
        >>> paradigm = Kss("paradigm")
        >>> text = "곱"
        >>> output = paradigm(text)
        >>> print(output)
        {'Action Verb': [('거나', '곱거나'), ('거늘', '곱거늘'), ('거니', '곱거니'), ('거니와', '곱거니와'), ('거드면', '곱거드면'), ('거든', '곱거든'), ('건', '곱건'), ('건마는', '곱건마는'), ('것다', '곱것다'), ('게', '곱게'), ('겠', '곱겠'), ('고', '곱고'), ('고도', '곱고도'), ('고말고', '곱고말고'), ('관데', '곱관데'), ('기', '곱기'), ('기로', '곱기로'), ('기로니', '곱기로니'), ('기로서', '곱기로서'), ('기로서니', '곱기로서니'), ('기로선들', '곱기로선들'), ('기에', '곱기에'), ('네', '곱네'), ('니', '곱니'), ('다', '곱다'), ('다가', '곱다가'), ('다가는', '곱다가는'), ('다간', '곱다간'), ('다니', '곱다니'), ('다마다', '곱다마다'), ('더', '곱더'), ('더구나', '곱더구나'), ('더구려', '곱더구려'), ('더군', '곱더군'), ('더냐', '곱더냐'), ('더뇨', '곱더뇨'), ('더니', '곱더니'), ('더니라', '곱더니라'), ('더니마는', '곱더니마는'), ('더니만', '곱더니만'), ('더니이까', '곱더니이까'), ('더니이다', '곱더니이다'), ('더라', '곱더라'), ('더라나', '곱더라나'), ('더라니', '곱더라니'), ('더라니까', '곱더라니까'), ('더라도', '곱더라도'), ('더라며', '곱더라며'), ('더라면', '곱더라면'), ('더라면서', '곱더라면서'), ('더라손', '곱더라손'), ('더라지', '곱더라지'), ('더람', '곱더람'), ('더이까', '곱더이까'), ('더이다', '곱더이다'), ('던', '곱던'), ('던가', '곱던가'), ('던감', '곱던감'), ('던걸', '곱던걸'), ('던고', '곱던고'), ('던데', '곱던데'), ('던바', '곱던바'), ('던지', '곱던지'), ('데', '곱데'), ('데요', '곱데요'), ('도다', '곱도다'), ('되', '곱되'), ('든', '곱든'), ('든가', '곱든가'), ('든지', '곱든지'), ('듯', '곱듯'), ('듯이', '곱듯이'), ('소이까', '곱소이까'), ('죠', '곱죠'), ('지마는', '곱지마는'), ('지만', '곱지만'), ('지요', '곱지요'), ('게', '곱게'), ('고는', '곱고는'), ('누', '곱누'), ('디', '곱디'), ('소', '곱소'), ('지', '곱지'), ('아', '곱아'), ('아도', '곱아도'), ('아라', '곱아라'), ('아서', '곱아서'), ('아야', '곱아야'), ('아야만', '곱아야만'), ('아야지', '곱아야지'), ('아요', '곱아요'), ('아지이다', '곱아지이다'), ('았', '곱았'), ('았었', '곱았었'), ('았자', '곱았자'), ('으나', '곱으나'), ('으나마', '곱으나마'), ('으니', '곱으니'), ('으니까', '곱으니까'), ('으니까는', '곱으니까는'), ('으니만치', '곱으니만치'), ('으니만큼', '곱으니만큼'), ('으려니와', '곱으려니와'), ('으려면', '곱으려면'), ('으련마는', '곱으련마는'), ('으렷다', '곱으렷다'), ('으리', '곱으리'), ('으리까', '곱으리까'), ('으리니', '곱으리니'), ('으리니라', '곱으리니라'), ('으리다', '곱으리다'), ('으리라', '곱으리라'), ('으리로다', '곱으리로다'), ('으리만치', '곱으리만치'), ('으리만큼', '곱으리만큼'), ('으리오', '곱으리오'), ('으매', '곱으매'), ('으며', '곱으며'), ('으면', '곱으면'), ('으면서', '곱으면서'), ('으므로', '곱으므로'), ('으사', '곱으사'), ('으세요', '곱으세요'), ('으셔요', '곱으셔요'), ('으소서', '곱으소서'), ('으시', '곱으시'), ('으시어요', '곱으시어요'), ('으오', '곱으오'), ('으오니까', '곱으오니까'), ('으오리까', '곱으오리까'), ('으오리다', '곱으오리다'), ('으오리이까', '곱으오리이까'), ('으오리이다', '곱으오리이다'), ('으오이다', '곱으오이다'), ('으옵', '곱으옵'), ('으옵나이까', '곱으옵나이까'), ('으옵나이다', '곱으옵나이다'), ('으옵니까', '곱으옵니까'), ('으옵니다', '곱으옵니다'), ('으옵디까', '곱으옵디까'), ('으옵디다', '곱으옵디다'), ('으옵소서', '곱으옵소서'), ('으옵시', '곱으옵시'), ('으와', '곱으와'), ('으우', '곱으우'), ('은', '곱은'), ('은걸', '곱은걸'), ('은들', '곱은들'), ('은즉', '곱은즉'), ('은즉슨', '곱은즉슨'), ('을', '곱을'), ('을걸', '곱을걸'), ('을까', '곱을까'), ('을는지', '곱을는지'), ('을라', '곱을라'), ('을라고', '곱을라고'), ('을러니', '곱을러니'), ('을러라', '곱을러라'), ('을런가', '곱을런가'), ('을런고', '곱을런고'), ('을레', '곱을레'), ('을레라', '곱을레라'), ('을망정', '곱을망정'), ('을밖에', '곱을밖에'), ('을뿐더러', '곱을뿐더러'), ('을새', '곱을새'), ('을세', '곱을세'), ('을세라', '곱을세라'), ('을세말이지', '곱을세말이지'), ('을수록', '곱을수록'), ('을시', '곱을시'), ('을쏘냐', '곱을쏘냐'), ('을쏜가', '곱을쏜가'), ('을지', '곱을지'), ('을지나', '곱을지나'), ('을지니', '곱을지니'), ('을지니라', '곱을지니라'), ('을지라', '곱을지라'), ('을지라도', '곱을지라도'), ('을지로다', '곱을지로다'), ('을지며', '곱을지며'), ('을지어다', '곱을지어다'), ('을지언정', '곱을지언정'), ('을진대', '곱을진대'), ('을진대는', '곱을진대는'), ('을진저', '곱을진저'), ('음', '곱음'), ('음에도', '곱음에도'), ('음에랴', '곱음에랴'), ('읍시오', '곱읍시오'), ('습네', '곱습네'), ('습늰다', '곱습늰다'), ('습니까', '곱습니까'), ('습니다', '곱습니다'), ('습디까', '곱습디까'), ('습디다', '곱습디다'), ('습딘다', '곱습딘다'), ('습죠', '곱습죠'), ('습지요', '곱습지요'), ('거라', '곱거라'), ('건대', '곱건대'), ('게', '곱게'), ('게끔', '곱게끔'), ('게나', '곱게나'), ('고는', '곱고는'), ('고서', '곱고서'), ('고야', '곱고야'), ('곤', '곱곤'), ('구려', '곱구려'), ('구먼', '곱구먼'), ('나', '곱나'), ('나니', '곱나니'), ('남', '곱남'), ('노니', '곱노니'), ('노라', '곱노라'), ('노라고', '곱노라고'), ('누나', '곱누나'), ('누먼', '곱누먼'), ('느라', '곱느라'), ('느라고', '곱느라고'), ('는구나', '곱는구나'), ('는구려', '곱는구려'), ('는군', '곱는군'), ('도록', '곱도록'), ('세나', '곱세나'), ('자', '곱자'), ('자고', '곱자고'), ('자꾸나', '곱자꾸나'), ('자느니', '곱자느니'), ('자니까', '곱자니까'), ('자마자', '곱자마자'), ('자며', '곱자며'), ('자면', '곱자면'), ('자면서', '곱자면서'), ('자손', '곱자손'), ('아다', '곱아다'), ('아다가', '곱아다가'), ('고자', '곱고자'), ('나이까', '곱나이까'), ('나이다', '곱나이다'), ('노라니', '곱노라니'), ('노라니까', '곱노라니까'), ('노라면', '곱노라면'), ('느냐', '곱느냐'), ('느냐고', '곱느냐고'), ('느뇨', '곱느뇨'), ('느니', '곱느니'), ('느니라', '곱느니라'), ('느니만', '곱느니만'), ('느니만치', '곱느니만치'), ('느니만큼', '곱느니만큼'), ('는', '곱는'), ('는가', '곱는가'), ('는감', '곱는감'), ('는걸', '곱는걸'), ('는고', '곱는고'), ('는데', '곱는데'), ('는뎁쇼', '곱는뎁쇼'), ('는바', '곱는바'), ('는지', '곱는지'), ('는지고', '곱는지고'), ('는지라', '곱는지라'), ('으라', '곱으라'), ('으라고', '곱으라고'), ('으라나', '곱으라나'), ('으라느니', '곱으라느니'), ('으라니까', '곱으라니까'), ('으라며', '곱으라며'), ('으라면서', '곱으라면서'), ('으라손', '곱으라손'), ('으락', '곱으락'), ('으란', '곱으란'), ('으람', '곱으람'), ('으랴', '곱으랴'), ('으러', '곱으러'), ('으려', '곱으려'), ('으려거든', '곱으려거든'), ('으려고', '곱으려고'), ('으려나', '곱으려나'), ('으려니', '곱으려니'), ('으려든', '곱으려든'), ('으려무나', '곱으려무나'), ('으련', '곱으련'), ('으렴', '곱으렴'), ('으렵니까', '곱으렵니까'), ('으렵니다', '곱으렵니다'), ('으마', '곱으마'), ('으사이다', '곱으사이다'), ('으세', '곱으세'), ('으시라', '곱으시라'), ('으시압', '곱으시압'), ('으십사', '곱으십사'), ('으십시다', '곱으십시다'), ('으십시오', '곱으십시오'), ('을거나', '곱을거나'), ('을게', '곱을게'), ('을깝쇼', '곱을깝쇼'), ('을라치면', '곱을라치면'), ('을락', '곱을락'), ('을래', '곱을래'), ('을작시면', '곱을작시면'), ('음세', '곱음세'), ('읍시다', '곱읍시다'), ('읍시사', '곱읍시사'), ('는다', '곱는다'), ('는다고', '곱는다고'), ('는다나', '곱는다나'), ('는다네', '곱는다네'), ('는다느니', '곱는다느니'), ('는다니', '곱는다니'), ('는다니까', '곱는다니까'), ('는다더라', '곱는다더라'), ('는다마는', '곱는다마는'), ('는다며', '곱는다며'), ('는다면', '곱는다면'), ('는다면서', '곱는다면서'), ('는다손', '곱는다손'), ('는다오', '곱는다오'), ('는다지', '곱는다지'), ('는단다', '곱는단다'), ('는담', '곱는담'), ('는답니까', '곱는답니까'), ('는답니다', '곱는답니다'), ('는답시고', '곱는답시고'), ('는대', '곱는대'), ('는대요', '곱는대요')], 'Descriptive Verb': [('거나', '곱거나'), ('거늘', '곱거늘'), ('거니', '곱거니'), ('거니와', '곱거니와'), ('거드면', '곱거드면'), ('거든', '곱거든'), ('건', '곱건'), ('건마는', '곱건마는'), ('것다', '곱것다'), ('게', '곱게'), ('겠', '곱겠'), ('고', '곱고'), ('고도', '곱고도'), ('고말고', '곱고말고'), ('관데', '곱관데'), ('기', '곱기'), ('기로', '곱기로'), ('기로니', '곱기로니'), ('기로서', '곱기로서'), ('기로서니', '곱기로서니'), ('기로선들', '곱기로선들'), ('기에', '곱기에'), ('네', '곱네'), ('니', '곱니'), ('다', '곱다'), ('다가', '곱다가'), ('다가는', '곱다가는'), ('다간', '곱다간'), ('다니', '곱다니'), ('다마다', '곱다마다'), ('더', '곱더'), ('더구나', '곱더구나'), ('더구려', '곱더구려'), ('더군', '곱더군'), ('더냐', '곱더냐'), ('더뇨', '곱더뇨'), ('더니', '곱더니'), ('더니라', '곱더니라'), ('더니마는', '곱더니마는'), ('더니만', '곱더니만'), ('더니이까', '곱더니이까'), ('더니이다', '곱더니이다'), ('더라', '곱더라'), ('더라나', '곱더라나'), ('더라니', '곱더라니'), ('더라니까', '곱더라니까'), ('더라도', '곱더라도'), ('더라며', '곱더라며'), ('더라면', '곱더라면'), ('더라면서', '곱더라면서'), ('더라손', '곱더라손'), ('더라지', '곱더라지'), ('더람', '곱더람'), ('더이까', '곱더이까'), ('더이다', '곱더이다'), ('던', '곱던'), ('던가', '곱던가'), ('던감', '곱던감'), ('던걸', '곱던걸'), ('던고', '곱던고'), ('던데', '곱던데'), ('던바', '곱던바'), ('던지', '곱던지'), ('데', '곱데'), ('데요', '곱데요'), ('도다', '곱도다'), ('되', '곱되'), ('든', '곱든'), ('든가', '곱든가'), ('든지', '곱든지'), ('듯', '곱듯'), ('듯이', '곱듯이'), ('소이까', '곱소이까'), ('죠', '곱죠'), ('지마는', '곱지마는'), ('지만', '곱지만'), ('지요', '곱지요'), ('게', '곱게'), ('고는', '곱고는'), ('누', '곱누'), ('디', '곱디'), ('소', '곱소'), ('지', '곱지'), ('아', '고와'), ('아도', '고와도'), ('아라', '고와라'), ('아서', '고와서'), ('아야', '고와야'), ('아야만', '고와야만'), ('아야지', '고와야지'), ('아요', '고와요'), ('아지이다', '고와지이다'), ('았', '고왔'), ('았었', '고왔었'), ('았자', '고왔자'), ('으나', '고우나'), ('으나마', '고우나마'), ('으니', '고우니'), ('으니까', '고우니까'), ('으니까는', '고우니까는'), ('으니만치', '고우니만치'), ('으니만큼', '고우니만큼'), ('으려니와', '고우려니와'), ('으려면', '고우려면'), ('으련마는', '고우련마는'), ('으렷다', '고우렷다'), ('으리', '고우리'), ('으리까', '고우리까'), ('으리니', '고우리니'), ('으리니라', '고우리니라'), ('으리다', '고우리다'), ('으리라', '고우리라'), ('으리로다', '고우리로다'), ('으리만치', '고우리만치'), ('으리만큼', '고우리만큼'), ('으리오', '고우리오'), ('으매', '고우매'), ('으며', '고우며'), ('으면', '고우면'), ('으면서', '고우면서'), ('으므로', '고우므로'), ('으사', '고우사'), ('으세요', '고우세요'), ('으셔요', '고우셔요'), ('으소서', '고우소서'), ('으시', '고우시'), ('으시어요', '고우시어요'), ('으오', '고우오'), ('으오니까', '고우오니까'), ('으오리까', '고우오리까'), ('으오리다', '고우오리다'), ('으오리이까', '고우오리이까'), ('으오리이다', '고우오리이다'), ('으오이다', '고우오이다'), ('으옵', '고우옵'), ('으옵나이까', '고우옵나이까'), ('으옵나이다', '고우옵나이다'), ('으옵니까', '고우옵니까'), ('으옵니다', '고우옵니다'), ('으옵디까', '고우옵디까'), ('으옵디다', '고우옵디다'), ('으옵소서', '고우옵소서'), ('으옵시', '고우옵시'), ('으와', '고우와'), ('으우', '고우우'), ('은', '고운'), ('은걸', '고운걸'), ('은들', '고운들'), ('은즉', '고운즉'), ('은즉슨', '고운즉슨'), ('을', '고울'), ('을걸', '고울걸'), ('을까', '고울까'), ('을는지', '고울는지'), ('을라', '고울라'), ('을라고', '고울라고'), ('을러니', '고울러니'), ('을러라', '고울러라'), ('을런가', '고울런가'), ('을런고', '고울런고'), ('을레', '고울레'), ('을레라', '고울레라'), ('을망정', '고울망정'), ('을밖에', '고울밖에'), ('을뿐더러', '고울뿐더러'), ('을새', '고울새'), ('을세', '고울세'), ('을세라', '고울세라'), ('을세말이지', '고울세말이지'), ('을수록', '고울수록'), ('을시', '고울시'), ('을쏘냐', '고울쏘냐'), ('을쏜가', '고울쏜가'), ('을지', '고울지'), ('을지나', '고울지나'), ('을지니', '고울지니'), ('을지니라', '고울지니라'), ('을지라', '고울지라'), ('을지라도', '고울지라도'), ('을지로다', '고울지로다'), ('을지며', '고울지며'), ('을지어다', '고울지어다'), ('을지언정', '고울지언정'), ('을진대', '고울진대'), ('을진대는', '고울진대는'), ('을진저', '고울진저'), ('음', '고움'), ('음에도', '고움에도'), ('음에랴', '고움에랴'), ('읍시오', '고웁시오'), ('습네', '곱습네'), ('습늰다', '곱습늰다'), ('습니까', '곱습니까'), ('습니다', '곱습니다'), ('습디까', '곱습디까'), ('습디다', '곱습디다'), ('습딘다', '곱습딘다'), ('습죠', '곱습죠'), ('습지요', '곱습지요'), ('구나', '곱구나'), ('구려', '곱구려'), ('군', '곱군'), ('다고', '곱다고'), ('다나', '곱다나'), ('다네', '곱다네'), ('다느니', '곱다느니'), ('다니', '곱다니'), ('다니까', '곱다니까'), ('다더라', '곱다더라'), ('다마는', '곱다마는'), ('다며', '곱다며'), ('다면', '곱다면'), ('다면서', '곱다면서'), ('다손', '곱다손'), ('다지', '곱다지'), ('단다', '곱단다'), ('담', '곱담'), ('답니까', '곱답니까'), ('답니다', '곱답니다'), ('답시고', '곱답시고'), ('대', '곱대'), ('대요', '곱대요'), ('디', '곱디'), ('우', '곱우'), ('으냐', '고우냐'), ('으냐고', '고우냐고'), ('으뇨', '고우뇨'), ('으니', '고우니'), ('으니라', '고우니라'), ('으이', '고우이'), ('은가', '고운가'), ('은감', '고운감'), ('은고', '고운고'), ('은데', '고운데'), ('은뎁쇼', '고운뎁쇼'), ('은지', '고운지'), ('을데라니', '고울데라니'), ('을시고', '고울시고')]}

    References:
        This was copied from [KoParadigm](https://github.com/Kyubyong/KoParadigm) and modified by Kss
    """
    text, finish = _check_text(text)

    if finish:
        return [] if isinstance(text, list) else {}

    num_workers = _check_num_workers(text, num_workers)

    if num_workers is not False and verbose:
        verbose = False
        logger.warn(
            "Verbose mode is not supported for multiprocessing. "
            "It will be turned off automatically."
        )

    return _run_job(
        func=partial(_paradigm, verbose=verbose),
        inputs=text,
        num_workers=num_workers,
    )


def _paradigm(text: str, verbose: bool = False):
    outputs = paradigm_obj.conjugate(text)

    if not outputs:
        return {}

    if verbose:
        prettify(outputs)

    outputs_dict = {}
    for output in outputs:
        outputs_dict[output[0]] = output[1]

    return outputs_dict
