#   Copyright 2000-2004 Michael Hudson-Doyle <micahel@gmail.com>
#
#                        All Rights Reserved
#
#
# Permission to use, copy, modify, and distribute this software and
# its documentation for any purpose is hereby granted without fee,
# provided that the above copyright notice appear in all copies and
# that both that copyright notice and this permission notice appear in
# supporting documentation.
#
# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

# (naming modules after builtin functions is not such a hot idea...)

# an KeyTrans instance translates Event objects into Command objects

# hmm, at what level do we want [C-i] and [tab] to be equivalent?
# [meta-a] and [esc a]?  obviously, these are going to be equivalent
# for the UnixConsole, but should they be for PygameConsole?

# it would in any situation seem to be a bad idea to bind, say, [tab]
# and [C-i] to *different* things... but should binding one bind the
# other?

# executive, temporary decision: [tab] and [C-i] are distinct, but
# [meta-key] is identified with [esc key].  We demand that any console
# class does quite a lot towards emulating a unix terminal.

from __future__ import annotations

from abc import ABC, abstractmethod
import unicodedata
from collections import deque
from typing import TYPE_CHECKING


# types
if TYPE_CHECKING:
    from .types import EventTuple


class InputTranslator(ABC):
    @abstractmethod
    def push(self, evt: EventTuple) -> None:
        pass

    @abstractmethod
    def get(self) -> EventTuple | None:
        return None

    @abstractmethod
    def empty(self) -> bool:
        return True


class KeymapTranslator(InputTranslator):
    def __init__(self, keymap, verbose=False, invalid_cls=None, character_cls=None):
        self.verbose = verbose
        from .keymap import compile_keymap, parse_keys

        self.keymap = keymap
        self.invalid_cls = invalid_cls
        self.character_cls = character_cls
        d = {}
        for keyspec, command in keymap:
            keyseq = tuple(parse_keys(keyspec))
            d[keyseq] = command
        if self.verbose:
            print(d)
        self.k = self.ck = compile_keymap(d, ())
        self.results = deque()
        self.stack = []

    def push(self, evt):
        if self.verbose:
            print("pushed", evt.data, end="")
        key = evt.data
        d = self.k.get(key)
        if isinstance(d, dict):
            if self.verbose:
                print("transition")
            self.stack.append(key)
            self.k = d
        else:
            if d is None:
                if self.verbose:
                    print("invalid")
                if self.stack or len(key) > 1 or unicodedata.category(key) == "C":
                    self.results.append((self.invalid_cls, self.stack + [key]))
                else:
                    # small optimization:
                    self.k[key] = self.character_cls
                    self.results.append((self.character_cls, [key]))
            else:
                if self.verbose:
                    print("matched", d)
                self.results.append((d, self.stack + [key]))
            self.stack = []
            self.k = self.ck

    def get(self):
        if self.results:
            return self.results.popleft()
        else:
            return None

    def empty(self) -> bool:
        return not self.results
