import pprint
import re
import kutil

def unescape_ktesc(s):
    """Resolve KTESC escape markers back to original characters.
    Use this for argument values used programmatically (filenames, etc.)."""
    def replace(match):
        hex_chars = match.group(1)
        result = ''
        for i in range(0, len(hex_chars), 4):
            result += chr(int(hex_chars[i:i+4], 16))
        return result
    return re.sub(r'KTESC([0-9a-f]+)KTESC', replace, s)

def escape_ktesc(s):
    """A KTESC marker for the characters of s -- the mirror of
    Target::escape_marker() in mac/target.cpp (4 lowercase hex digits per
    byte).  The marker is inert through every re-read and through the
    target's typographic transform pass, and decodes back to the characters
    at final escape resolution (ktesc_resolve)."""
    return 'KTESC' + ''.join(f'{ord(c):04x}' for c in s) + 'KTESC'

# The characters the SKS targets' typographic transforms act on: the
# hyphen runs (-- and ---), the quote conventions (` ' `` ''), and ~.
# Verbatim text (@c, @code, @source_listing) must reach the output exactly
# as written, so the code klammers hide each of these as a KTESC marker --
# a transform source can then never match -- and the markers decode after
# the transform pass has run.
# SYNC: the transform tables of the html and txt targets in
# sks/target/target.k.  A transform built from a new character needs it
# added here, or verbatim text will show the transformed form.
TYPOGRAPHIC_CHARS = "-'`~"

def hide_typographic(s):
    """Hide the typographically active characters of s as KTESC markers so
    the target's transform pass cannot change verbatim text."""
    for c in TYPOGRAPHIC_CHARS:
        s = s.replace(c, escape_ktesc(c))
    return s

class Klammer_base:
    def __init__(self, K):
        #args = {k:escape(v) for k, v in K.__dict__.items()
        args = {k:v for k, v in K.__dict__.items()
                if not k.startswith('__')}
        for key in args:
            setattr(self, key, args[key])
        #setattr(self, "_klammer_name", klammer_name)
        #pprint.pprint(self.__dict__)


    def html(self):
        #return '[{}: HTML]'.format(self.__class__.__name__)
        return None

    def tex(self):
        #return '[{}: LaTeX]'.format(self.__class__.__name__)
        return None

    def txt(self):
        #return '[{}: Plain text]'.format(self.__class__.__name__)
        return None

    def show(self, label=""):
        if label:
            print(label)
        pprint.pprint(self.__dict__)

    def __str__(self):
        result = None
        if self.K_target == 'html':
            result = self.html()
        elif self.K_target in {'tex', 'pdf'}:
            result = kutil.escape(self.tex())
        elif self.K_target == 'txt':
            result = self.txt()
        if result is None:
            #print(self.__dict__)
            raise Exception(
                f'Target "{self.K_target}" is undefined for klammer "@{self.K_klammer}"')
        return result
