#!/usr/bin/env python

import os
import sys, time
import traceback
import alarmdecoder

def handle_firmware(stage, **kwargs):
    if stage == alarmdecoder.util.Firmware.STAGE_START:
        handle_firmware.wait_tick = 0
        handle_firmware.upload_tick = 0
    elif stage == alarmdecoder.util.Firmware.STAGE_WAITING:
        if handle_firmware.wait_tick == 0:
            sys.stdout.write('Waiting for device.')
        handle_firmware.wait_tick += 1

        sys.stdout.write('.')
        sys.stdout.flush()
    elif stage == alarmdecoder.util.Firmware.STAGE_BOOT:
        if handle_firmware.wait_tick > 0: print("")
        print("Rebooting device..")
    elif stage == alarmdecoder.util.Firmware.STAGE_LOAD:
        print('Waiting for boot loader..')
    elif stage == alarmdecoder.util.Firmware.STAGE_UPLOADING:
        if handle_firmware.upload_tick == 0:
            sys.stdout.write('Uploading firmware.')

        handle_firmware.upload_tick += 1

        if handle_firmware.upload_tick % 30 == 0:
            sys.stdout.write('.')
            sys.stdout.flush()
    elif stage == alarmdecoder.util.Firmware.STAGE_DONE:
        print("\r\nDone!")
    elif stage == alarmdecoder.util.Firmware.STAGE_ERROR:
        print("\r\nError: {0}".format(kwargs.get("error", "")))
    elif stage == alarmdecoder.util.Firmware.STAGE_DEBUG:
        print("\r\nDBG: {0}".format(kwargs.get("data", "")))

def main():
    device = '/dev/ttyUSB0'
    firmware = None
    baudrate = 115200

    if len(sys.argv) < 3:
        print("Syntax: {0} <firmware> [device path or hostname:port] [baudrate=115200]".format(sys.argv[0]))
        sys.exit(1)

    firmware = sys.argv[1]
    device = sys.argv[2]

    if len(sys.argv) > 3:
        baudrate = sys.argv[3]

    debug = os.environ.get("ALARMDECODER_DEBUG") is not None
    print("Flashing device: {0} - {2} baud\r\nFirmware: {1}".format(device, firmware, baudrate))

    dev = None
    try:
        if ':' in device:
            hostname, port = device.split(':')
            dev = alarmdecoder.devices.SocketDevice(interface=(hostname, int(port)))
        else:
            dev = alarmdecoder.devices.SerialDevice(interface=device)

        dev.open(baudrate=baudrate, no_reader_thread=True)

        time.sleep(3)
        alarmdecoder.util.Firmware.upload(dev, firmware, handle_firmware, debug=debug)

    except alarmdecoder.util.NoDeviceError as ex:
        print("Error: Could not find device: {0}".format(ex))
    except alarmdecoder.util.UploadError as ex:
        print("Error: Error uploading firmware: {0}".format(ex))
    except Exception as ex:
        print("Error: {0}: {1}".format(ex, traceback.format_exc()))
    finally:
        if dev is not None:
            dev.close()

if __name__ == "__main__":
    main()
