#!/usr/bin/python3
"""
@file
@ingroup timeplot
@copyright ESO - European Southern Observatory

@brief m1 timeplot  separate also with simulator options
"""
import sys
import argparse
import os
import logging
import time
from taurus.qt.qtgui.application import TaurusApplication  # # pylint: disable=C0412

# View: main timeplot widget
from timeplot.timeplot_wdg import TimePlotTrackingErrorWidget
# Data: various data source
# subscriber to plot real data
from timeplot.timeplotdata.data_m1data_subscriber import DataTimePlotSubscriber
from timeplot.timeplotdata.timeplot_data_subscriber_shm import DataTimePlotSubscriberShm
# Simulator for test
from timeplot.timeplotdata.timeplot_data_sine_wave import TimePlotDataSineWave
from timeplot.timeplotdata.timeplot_data_timer import TimePlotDataTimer
from timeplot.timeplotdata.timeplot_data_shmem_tm import DataSimulatonSharedMemoryTm
# from timeplot.timeplotdata.timeplot_shmem_handler import DataSimulatonSharedMemory


if __name__ == "__main__":
    """
    Examples:
    % m1mongui_timeplot -i sim_sine -d 6,8
    % m1mongui_timeplot -i sim_shm -d 6,8
    % m1mongui_timeplot -i sim_sine -a 198.19.194.32 -p 5611 -d 6,8


    >> Using Demo Publisher
    step-1: Start demo publisher (for zeros): 
    % m1DataPub -k 200 -t FEPerformances --port 5611 -v -z 1000
    % m1DataPub -k 200 -t FEPerformances --port 5611 -v -z 1000 -u trkErr

    step-2: Start timeplot widget
    % m1mongui_timeplot --input subscriber_shm -a 127.0.0.1 -p 5611 -s 1

    >> Lab data
    % m1mongui_timeplot --input subscriber_shm -a 198.19.194.32 -p 5611 -d 5,8
    % m1mongui_timeplot --input subscriber_shm -a 198.19.194.32 -p 5611 -d 6,8

    >> Simulation
    % m1mongui_timeplot -i sim_sine -d 6,8
    % m1mongui_timeplot -i sim_shm -d 6,8

    >> Help
    The widget can be started up with other simulation options, see help: 
    % m1mongui_timeplot -h


    >> Performance test (for developer only)
    %  python3 -m cProfile  m1mongui_timeplot.py -i subscriber_shm -a 198.19.194.32 -p 5611 -d 6,8  >> my_wdg.profile
    %  python3 -m trace --trace  m1mongui_timeplot.py -i subscriber_shm -a 198.19.194.32 -p 5611 -d 6,8  >> my_wdg.trace 

    """

    parser = argparse.ArgumentParser(description='M1 Timeplot Widget - test')
    parser.add_argument('-i', '--input', default="subscriber_shm",
                        choices=['sim_sine', 'sim_shm', 'sim_threaded', "subscriber", "subscriber_shm"],
                        help="specify input data provider, e.g. simulator")
    # parser.add_argument('-d', '--dimension', default=(5, 5))
    parser.add_argument('-d', '--dimension', type=lambda x: tuple(map(float, x.split(','))),
                        default=(5, 5),
                        help='width and height of figure separated by commas (e.g. 8,6)')
    parser.add_argument('-p', '--port', default=5611,
                        help='port number of publisher')

    parser.add_argument('-a', '--address', default="198.19.194.32",
                        help='address e.g. 127.0.0.1 of publisher')
    parser.add_argument('-s', '--segments', type=lambda x: tuple(map(float, x.split(','))),
                        default=(74, 75, 87, 88, 89),
                        help='segments to display initially, max 5, available in lab: 74, 75, 87, 88, 89, 102')
    parser.add_argument('-v', '--save', action='store_true',
                        help='save the first 10 sec as gif')

    args = parser.parse_args()
    demo_data = args.input

    fig_width, fig_height = args.dimension

    # Create Taurus application
    app = TaurusApplication(sys.argv)
    # widget = TimePlotWidget()
    widget = TimePlotTrackingErrorWidget()

    # widget.shm_data = ShmM1MonGui(30, 30*300, 15, "MyName")
    # widget.shm_data = ShmM1MonGui(30, 30 * 3, 798 * 6*3, "MyName")

    NUM_SEGMENTS = 798

    # Set size
    widget.set_plot_size(fig_width, fig_height)
    femon_sub = None

    # Windows title
    title = widget.windowTitle()  # M1 Monitoring Time Plot
    segments = args.segments

    # Set Simulation class
    if demo_data == "sim_sine":
        # sine wave calculated
        # widget.data_source = TimePlotDataSineWaveWithShift()
        widget.data_source = TimePlotDataSineWave()

        widget.data_source.start()
        widget.data_source.logger.setLevel(logging.INFO)
        widget.setWindowTitle(title + " === SIMULATION")
        segments = (1, 2, 3, 4, 5)
    elif demo_data == "sim_shm":

        """ note: the shared memory take ~15 sec to create
           # NUM_SEGMENTS = 798
           # NUM_STORED_STEPS = 30 * 2 * 10
           # 10 minutes = 30sec*2 *10
           """
        NUM_SEGMENTS = 6  # 798
        NUM_STORED_STEPS = 30 * 2  # total number of stored steps
        num_pars = widget.get_number_of_params()  # 3 * 6 + 3 = 21
        # shared memory test on/off signal
        widget.data_source = DataSimulatonSharedMemoryTm(30,  # buffer_size for rotation
                                                         NUM_STORED_STEPS,  # shm  row size, multiple of biff size
                                                         NUM_SEGMENTS * num_pars,
                                                         "Simulation")

        widget.data_source.start_writer()
        widget.data_source.logger.setLevel(logging.INFO)

        # a.start_reader()
        # Wait for the processes to finish

        # Stop SHM writer, is taken cared during closed event of the gui
        # threading.Timer(30.0, widget.shm_data.stop).start()

        # Current data
        # print("Test SHM: Get section of data")
        # widget.shm_data.get_current_data(1,""Pact Tracking Error",1)

        # widget.demo_timer.start(1000)
        widget.setWindowTitle(title + " === SIMULATION Shared Memory Data input")
        segments = (1, 2, 3, 4, 5)
    elif demo_data == "sim_threaded":
        widget.data_source = TimePlotDataTimer()

        widget.setWindowTitle(title + " === SIMULATION Data input from Threads")
    elif demo_data in ["subscriber", "subscriber_shm"]:
        from m1mongui.comms.m1datasub import M1DataSub

        port = int(args.port)  # 5561
        address = args.address  # "127.0.0.1"

        if demo_data == "subscriber":
            timeplot_data_sub = DataTimePlotSubscriber()
        else:
            timeplot_data_sub = DataTimePlotSubscriberShm()
            logFormatter = logging.Formatter(
                "%(asctime)s [%(threadName)-12.12s] [%(levelname)-5.5s]  %(message)s")
            # shm_m1.logger.addHandler(logging.StreamHandler(sys.stdout))

            logging_handler = logging.StreamHandler()
            logging_handler.setFormatter(logFormatter)
            # timeplot_data_sub.logger.addHandler(logging_handler)
            # timeplot_data_sub.logger.setLevel(logging.DEBUG)

        print(f"subscriber address:{address} port:{port}")

        # feinfomon_performances_sub
        femon_sub = M1DataSub(
            model=timeplot_data_sub,
            topics=["FEPerformances"],
            address=address,  # "198.19.194.32",  #address,  # self._configuration.femon_address,
            port=port,
            # port=int(port),
        )
        widget.data_source = timeplot_data_sub
        femon_sub.setLogLevel(logging.WARNING)
        femon_sub.start()
        widget.data_source.start()
        widget.setWindowTitle(title + " === Address: " + address + " Port: " + str(port))
    else:
        print(f"Not supported demo: {demo_data}")

    widget.set_num_segments(NUM_SEGMENTS)

    # Set segments
    widget.set_segments(segments)

    if args.save:
        print("Set frame=30 for the animation")
        # widget.animation.get_num_frames
        print("saving the first few sec as gif, please wait. GUI will start after that.")
        time.sleep(2)
        if femon_sub is not None:
            femon_sub.setLogLevel(logging.WARNING)
        widget.save_time_plot()
        if femon_sub is not None:
            femon_sub.setLogLevel(logging.WARNING)
            # femon_sub.setLogLevel(logging.INFO)

    widget.show()

    # the current process
    pid = os.getpid()
    print(pid)

    res = app.exec_()
    if femon_sub is not None:
        femon_sub.requestInterruption()
        # del femon_sub
    # time.sleep(2)
    print(">>> Timeplot Widget Closed")

    sys.exit(res)
