#!/usr/bin/env python

import argparse
from time import sleep
import numpy as np
from matplotlib import pyplot as plt

from cameras.cameraclient import CameraClient


def main():
    commands = ["restart", "roi", "status", "test", "show", "save"]
    commands.sort()
    printable_commands = ", ".join(commands)

    parser = argparse.ArgumentParser(description="CLI Cam (esh)")
    parser.add_argument("-c", "--camera", help="camera name", default="SATES24-CAMS161-M1")
    parser.add_argument("-v", "--verbose", help="verbose output", action="store_true")

    subparsers = parser.add_subparsers(title="commands", dest="command", help=printable_commands)
    subparser_restart = subparsers.add_parser("restart", description="Restart camera server")
    subparser_roi     = subparsers.add_parser("roi", description="Set ROI")
    subparser_status  = subparsers.add_parser("status", description="Print status")
    subparser_test    = subparsers.add_parser("test", description="Test setting ROIs")
    subparser_show    = subparsers.add_parser("show", description="Show current image")
    subparser_save    = subparsers.add_parser("save", description="Save current image")

    for sp in subparsers.choices.values():
        sp.add_argument("-v", "--verbose", help="verbose output", action="store_true")

    subparser_restart.add_argument("-r", "--reset", help="reset ROI", action="store_true")

    subparser_roi.add_argument("xmin", type=int, help="x min")
    subparser_roi.add_argument("xmax", type=int, help="x max")
    subparser_roi.add_argument("ymin", type=int, help="y min")
    subparser_roi.add_argument("ymax", type=int, help="y max")

    subparser_save.add_argument("filename", help="Output filename")

    clargs = parser.parse_args()
    command = clargs.command
    if command is None:
        parser.print_help()
        raise SystemExit(1)

    camera = CameraClient(clargs.camera)

    if clargs.verbose:
        print(camera)
        print(f"command: {command}")
#        print(clargs)

    if command == "restart":
        do_restart(camera, clargs)
    elif command == "roi":
        do_roi(camera, clargs)
    elif command == "test":
        do_test(camera, clargs)
    elif command == "status":
        do_status(camera, clargs)
    elif command == "show":
        do_show(camera, clargs)
    elif command == "save":
        do_save(camera, clargs)
    else:
        print(f"nothing assigned to command: {command}")
        parser.print_help()
        raise SystemExit(2)



def do_restart(camera, clargs):
    if not clargs.reset:
        roi = camera.get_roi()
    camera.restart()
    if not clargs.reset:
        camera.set_roi(*roi, debug=clargs.verbose) #TODO: workaround! why does the first try always set to: [101, 2400, 100, 2061]?
        camera.set_roi(*roi, debug=clargs.verbose)

def do_roi(camera, clargs):
    camera.set_roi(clargs.xmin, clargs.xmax, clargs.ymin, clargs.ymax, debug=clargs.verbose)

def do_status(camera, clargs):
    camera.status

def do_test(camera, _clargs):
    camera.reset_roi() # [1, 2560, 1, 2160]
    print(camera.get_roi())

    for i in (1, 10, 100, 200, 300, 999, 1000, 1001):
        camera.set_roi(i, 1500, i, 1900, debug=True)


def do_show(camera, _clargs):
    img = camera.get()
    proj_x = img.sum(axis=1)
    proj_y = img.sum(axis=0)

    fig = plt.figure()

#    ax_px  = fig.add_subplot(222)
#    ax_py  = fig.add_subplot(223)
#    ax_img = fig.add_subplot(221, sharex = ax_px, sharey = ax_py)

    left, width = bottom, height = 0.1, 0.65
    spacing = 0.005

    rect_img = [left, bottom, width, height]
    rect_px  = [left, bottom + height + spacing, width, 0.2]
    rect_py  = [left + width + spacing, bottom, 0.2, height]

    ax_img = plt.axes(rect_img)
    ax_px  = plt.axes(rect_px)
    ax_py  = plt.axes(rect_py)

    ax_img.tick_params(direction='in', top=True, right=True)
    ax_px.tick_params(direction='in', labelbottom=False)
    ax_py.tick_params(direction='in', labelleft=False)

    ax_img.imshow(img.T, origin="lower", interpolation="none")
    ax_px.plot(proj_x)
    ax_py.plot(proj_y, range(len(proj_y)))

#    aspx = np.diff(ax_px.get_xlim())[0] / np.diff(ax_px.get_ylim())[0]
#    ax_px.set_aspect(aspx)

#    aspy = np.diff(ax_py.get_xlim())[0] / np.diff(ax_py.get_ylim())[0]
#    ax_py.set_aspect(aspy)

    plt.show()


def do_save(camera, clargs):
    ext = ".npy"
    filename = clargs.filename
    filename = filename if filename.endswith(ext) else filename + ext
    img = camera.get()
    img.dump(filename)





if __name__ == "__main__":
    main()

    #CA client library tcp receive thread terminating due to a non-standard C++ exception
    #FATAL: exception not rethrown
    #Aborted (core dumped)

    # "solved" by
    sleep(0.001)