from argparse import ArgumentParser, RawDescriptionHelpFormatter
import codetable


def hexfmt4(val):
   """ 4bit-Zahl mit hex(val) umwandeln und das Ergebnis wie
       folgt anpassen:
       '0x5'  -> '5'
   """
   if val > 15:
       raise SystemExit("hexfmt4 overflow: %d" % val)
   s = hex(val)
   s = s[2:]
   return s

def hexfmt8(val):
   """ 8bit-Zahl hexadezimal ausgeben """
   return "%s%s" % (hexfmt4(val >> 4), hexfmt4(val & 0xf))


class Table:
   """ Basis-Klasse """

   def __init__(self, rows, cols, start, title):
       self.rows = rows
       self.cols = cols
       self.start = start
       self.title = title
       # Fehler-Zeichen aendern
       codetable.ERRCHR = ' '

   def _empty(self,val):
       return "%3d:  " % val

   def _cell(self, val):
       return self._empty()

   def __str__(self):
       lines = []
       lines.append(self.title)
       lines.append("")
       y = 0
       while y < self.rows:
           x = 0
           line = []
           while x < self.cols:
               v = self.start + x * self.rows + y
               line.append(self._cell(v))
               x += 1
           lines.append("  ".join(line))
           y += 1
       return "\n".join(lines)


class ASCIIDec(Table):
   """ASCII-Codes (dezimal)"""

   def __init__(self, rows, cols, start):
       super().__init__(
           rows, cols, start, "ASCII-Codes (dezimal)")

   def _cell(self, val):
       if (val >= 32) and  (val <= 126):
           return "%3d: %c" % (val, chr(val))
       else:
           return self._empty(val)


class ASCIIHex(Table):
   """ASCII-Codes (hexadezimal)"""

   def __init__(self, rows, cols, start):
       super().__init__(
           rows, cols, start, "ASCII-Codes (hexadezimal)")

   def _empty(self,val):
       return "$%s:  " % hexfmt8(val)

   def _cell(self, val):
       if (val >= 32) and  (val <= 126):
           return "$%s: %c" % (hexfmt8(val), chr(val))
       else:
           return self._empty(val)


class ASCIIC64(Table):
   """ ASCII-Codes C64 (Basis-Klasse) """

   def __init__(self, rows, cols, start, title):
       super().__init__(rows, cols, start, title)
       # Liste der unterstuetzten Steuercodes
       self.spec_codes = [
           5,   # weiss
           18,  # invers an
           28,  # rot
           30,  # gruen
           31,  # blau
           144, # schwarz
           146, # invers aus (reset)
           149, # braun
           156, # magenta
           159, # cyan
       ]

   def _get(self, val, font):
       """ Liefert einen String mit dem Zeichen; bei Steuercodes
           wird ein Stern als Zeichen verwendet und der String
           mit einem Reset-Code abgeschlossen.
       """
       ch = codetable.asc2chr(val, font)
       if val in self.spec_codes:
           ch = ch + '*'
       return ch + codetable.RESET


class ASCIIC64Font1(ASCIIC64):
   """ ASCII-Codes C64 (Zeichensatz 1) """

   def __init__(self, rows, cols, start):
       super().__init__(
           rows, cols, start, "ASCII-Codes C64 (Zeichensatz 1)")

   def _cell(self, val):
       return "%3d: %s" % (val, self._get(val, 1))


class ASCIIC64Font2(ASCIIC64):
   """ ASCII-Codes C64 (Zeichensatz 2) """

   def __init__(self, rows, cols, start):
       super().__init__(
           rows, cols, start, "ASCII-Codes C64 (Zeichensatz 2)")

   def _cell(self, val):
       return "%3d: %s" % (val, self._get(val, 2))


class SCREENC64Font1(Table):

   def __init__(self, rows, cols, start):
       super().__init__(
           rows, cols, start, "Screen-Codes C64 (Zeichensatz 1)")

   def _cell(self, val):
       return "%3d: %c" % (val, codetable.scr2chr(val, 1))


class SCREENC64Font2(Table):

   def __init__(self, rows, cols, start):
       super().__init__(
           rows, cols, start, "Screen-Codes C64 (Zeichensatz 2)")

   def _cell(self, val):
       return "%3d: %c" % (val, codetable.scr2chr(val, 2))


desc = """Zeichensatz-Tabellen darstellen:
 ascdec:      ASCII-Codes (dezimal)
 aschex:      ASCII-Codes (hexadezimal)
 c64ascfont1: ASCII-Codes C64 (Zeichensatz 1)
 c64ascfont2: ASCII-Codes C64 (Zeichensatz 2)
 c64scrfont1: Screen-Codes C64 (Zeichensatz 1)
 c64scrfont2: Screen-Codes C64 (Zeichensatz 2)
"""

if __name__ == '__main__':

   parser = ArgumentParser(prog='codes.py',
       formatter_class=RawDescriptionHelpFormatter,
       description = desc)
   parser.add_argument('table', choices = [
       'ascdec', 'aschex', 'c64ascfont1', 'c64ascfont2',
       'c64scrfont1', 'c64scrfont2'
       ], help="darzustellende Tabelle")
   args = parser.parse_args()

   if args.table == "ascdec":
       tab = ASCIIDec(16, 6, 32) # ASCII 32-127
   elif args.table == "aschex":
       tab = ASCIIHex(16, 6, 32) # ASCII 32-127
   elif args.table == "c64ascfont1":
       tab = ASCIIC64Font1(16, 10, 0) # ASC 0-159
   elif args.table == "c64ascfont2":
       tab = ASCIIC64Font2(16, 10, 0) # ASC 0-159
   elif args.table == "c64scrfont1":
       tab = SCREENC64Font1(16, 6, 0) # SCR 0-95
   elif args.table == "c64scrfont2":
       tab = SCREENC64Font2(16, 6, 0) # SCR 0-95

   print(tab)