import json, hashlib, re
from .adaptive import AdaptiveMemory

class TokenchatUniversal:
    def __init__(self, adaptive=True):
        self.vocab = {}
        self.inverse_vocab = {}
        self.next_id = 1
        self.protocol_version = "TUP-5.0"
        self.adaptive = AdaptiveMemory() if adaptive else None

    def _tokenize(self, text):
        tokens = re.findall(r"\w+|[^\w\s]", text, re.UNICODE)
        ids = []
        for token in tokens:
            if token not in self.vocab:
                token_hash = hashlib.sha1(token.encode()).hexdigest()[:6]
                self.vocab[token] = self.next_id
                self.inverse_vocab[self.next_id] = token
                self.next_id += 1
            ids.append(self.vocab[token])
        return ids

    def _detokenize(self, ids):
        tokens = [self.inverse_vocab.get(i, "?") for i in ids]
        return " ".join(tokens).replace(" .", ".").replace(" ,", ",")

    def encode(self, text):
        token_ids = self._tokenize(text)
        return json.dumps({
            "version": self.protocol_version,
            "tokens": token_ids,
            "original_text": text
        })

    def decode(self, tup_json):
        try:
            data = json.loads(tup_json)
            if "tokens" in data:
                return self._detokenize(data["tokens"])
            return tup_json
        except json.JSONDecodeError:
            return tup_json

    def bridge(self, ai_func, user_text, compressor=None, translator=None):
        if self.adaptive:
            remembered = self.adaptive.recall(user_text)
            if remembered:
                return remembered

        encoded = self.encode(user_text)
        if translator: encoded = translator.translate(encoded)
        if compressor: encoded = compressor.compress(encoded)

        ai_response = ai_func(encoded)

        if compressor: ai_response = compressor.decompress(ai_response)
        if translator: ai_response = translator.untranslate(ai_response)

        decoded = self.decode(ai_response)

        if self.adaptive:
            self.adaptive.update(user_text, decoded)

        return decoded