import binascii
from usbrply.printer import Printer, indented, indent_inc, indent_dec
from usbrply.pyprinter import bytes2AnonArray


class TextFT2232CPrinter(object):
    def __init__(self, args):
        self.ascii = args.ascii

    def next_json(self, j, prefix=None):
        if j['type'] == 'read':
            interface = j['interface']
            data = j['data']
            n = len(data) / 2
            prefix = j['prefix']
            if self.ascii:
                indented("%u r %s: %s" %
                         (interface, n, binascii.unhexlify(data)))
            else:
                indented("%u r %s: 0x%s" % (interface, n, data))
                indented("  %s" % (binascii.hexlify(prefix, )))
        elif j['type'] == 'write':
            interface = j['interface']
            data = j['data']
            n = len(data) / 2
            if self.ascii:
                indented("%u w %s: %s" %
                         (interface, n, binascii.unhexlify(data)))
            else:
                indented("%u w %s: 0x%s" % (interface, n, data))
        elif j['type'] == 'SET_DATA':
            indented(
                "i%s SET_DATA: parity %s, stop bits %s, break %s" %
                (j['interface'], j['parity'], j['stopbits'], j['breakon']))
        else:
            indented("i%s %s: %s" % (j['interface'], j['type'], j))

    def comment(self, s):
        indented('%s' % (s, ))

    def header(self):
        self.comment("Generated by usbrply-serial FT2232C")

    def footer(self):
        pass

    def run(self, j):
        print("")
        print("")
        print("")

        self.header()

        for d in j["data"]:
            self.next_json(d)

        self.footer()


class JSONSPrinter(object):
    def run(self, j):
        print(json.dumps(j, sort_keys=True, indent=4, separators=(',', ': ')))


class PythonFT2232CPrinter(object):
    def __init__(self, args):
        self.ascii = args.ascii
        self.wrapper = args.wrapper

    def next_json(self, j, prefix=None):
        if j['type'] == 'read':
            interface = j['interface']
            data = binascii.unhexlify(j["data"])
            indented("buff = ser%u.read(%u)" % (interface, len(data)))
            indented("validate_read(%s, buff, \"%s\")" %
                     (bytes2AnonArray(data), "packet"))
        elif j['type'] == 'write':
            data_str = bytes2AnonArray(binascii.unhexlify(j["data"]))
            interface = j['interface']
            indented("ser%u.write(%s)" % (interface, data_str))
        else:
            # assert 0
            print('# next_json: %s' % (j['type'], ))

    def comment(self, s):
        indented('# %s' % (s, ))

    def header(self):
        if not self.wrapper:
            return
        # self.comment("Generated by usbrply-serial FT2232C")
        print('''
#!/usr/bin/env python3
import binascii
import time
import serial

def validate_read(expected, actual, msg):
    if expected != actual:
        print('Failed %s' % msg)
        print('  Expected; %s' % binascii.hexlify(expected,))
        print('  Actual:   %s' % binascii.hexlify(actual,))
        #raise Exception('failed validate: %s' % msg)

''')
        print('def replay(ser0):')
        indent_inc()

    def footer(self):
        indent_dec()
        if not self.wrapper:
            return
        print('''
if __name__ == "__main__":
    import argparse 
    
    parser = argparse.ArgumentParser(description='Replay captured USB-serial packets')
    parser.add_argument('-p',
                        "--port",
                        default="/dev/ttyUSB0",
                        help="")
    args = parser.parse_args()

    serial0 = serial.Serial(
        args.port,
        baudrate=115200,
        bytesize=serial.EIGHTBITS,
        parity=serial.PARITY_NONE,
        stopbits=serial.STOPBITS_ONE,
        rtscts=False,
        dsrdtr=False,
        xonxoff=False,
        timeout=0,
        writeTimeout=None)
    replay(serial0)

''')

    def run(self, j):
        self.header()

        for d in j["data"]:
            self.next_json(d)

        self.footer()
