"""
Perform tests by creating NativeUI and using qtbot to read the
GUI directly and assert readings (assumes a known dump file).

Make sure your PYTHONPATH var is set to the full path of:
'/<your_hev_root_dir>/hev/NativeUI'.
"""
import os
import tempfile
import statistics
import pytest
import hevclient
from tests.integration.integration_utils import start_background_arduinosim_hevserver, \
    kill_process_group, assert_posix, assert_pythonpath
from NativeUI import set_window_size, interpret_resolution
from NativeUI import NativeUI

# Overwrite the mm file for OS agnostic testing
hevclient.mmFileName = tempfile.gettempdir() + os.path.sep + "HEVCLIENT_last_Data.mmap"


@pytest.fixture(scope="class")
def background_procs():
    """
    Fixutre to start the Arduino emulator and hevserver as background
    processes and kill the processes after the test.
    """
    background_processes = start_background_arduinosim_hevserver()
    yield background_processes
    if background_processes is not None:
        for proc in background_processes:
            kill_process_group(proc.pid)


@pytest.fixture
def native_ui(qtbot):
    """
    Fixture to inject the NativeUI. Fixture waits until GUI is shown.
    """
    # if not QtWidgets.QApplication.instance():
    #     app = QtWidgets.QApplication(sys.argv)
    # else:
    #     app = QtWidgets.QApplication.instance()

    res = interpret_resolution(input_string='1024*768')
    native_gui = NativeUI(resolution=res)
    set_window_size(
        native_gui,
        resolution='1024*768',
        windowed=False,
    )
    qtbot.addWidget(native_gui)
    native_gui.show()
    qtbot.waitForWindowShown(native_gui)
    return native_gui


def test_steady_state_measurements_from_gui(background_procs, native_ui, qtbot):
    """
    Create the NativeUI and use qtbot to read the measurement
    GUI items directly from the UI and assert the steady-state
    of those readings (assumes a known dump file).
    """
    assert_posix()
    assert_pythonpath()

    # wait for approx 1 min because it takes that
    # long for the real dump data to start reading meaningful values.
    qtbot.wait(90000)

    # To store measurement readings read straight from the GUI
    plateau_pressures = []
    respiratory_rates = []
    fio2_percentages = []
    exhaled_tidal_volumes = []
    exhaled_minute_volumes = []
    peeps = []

    sample_size = 5
    time_step_ms = 4000
    widget_measurement_list = native_ui.widgets.normal_measurements.widget_list
    for _ in range(sample_size):
        plateau_pressure_sample = float(widget_measurement_list[0].value_display.text())
        plateau_pressures.append(plateau_pressure_sample)
        assert plateau_pressure_sample < 20  # expected: 19.5
        assert plateau_pressure_sample > 19

        respiratory_rate_sample = float(widget_measurement_list[1].value_display.text())
        respiratory_rates.append(respiratory_rate_sample)
        assert respiratory_rate_sample < 16.0  # expected: 15.0
        assert respiratory_rate_sample > 14.0

        fio2_percentage_sample = float(widget_measurement_list[2].value_display.text())
        fio2_percentages.append(fio2_percentage_sample)
        assert fio2_percentage_sample < 105  # expected: 103.8
        assert fio2_percentage_sample > 102

        exhaled_tidal_sample = float(widget_measurement_list[3].value_display.text())
        exhaled_tidal_volumes.append(exhaled_tidal_sample)
        assert exhaled_tidal_sample < 276  # expected: 275.7
        assert exhaled_tidal_sample > 275

        exhaled_minute_sample = float(widget_measurement_list[4].value_display.text())
        exhaled_minute_volumes.append(exhaled_minute_sample)
        assert exhaled_minute_sample < 4.5  # expected: 4.2
        assert exhaled_minute_sample > 3.5

        peeps_sample = float(widget_measurement_list[5].value_display.text())
        peeps.append(peeps_sample)
        assert peeps_sample < 8.5  # expected: 8.2
        assert peeps_sample > 8.0
        qtbot.wait(time_step_ms)

    # Calculate standard deviation
    plateau_pressures_stdev = statistics.stdev(plateau_pressures)
    respiratory_rates_stdev = statistics.stdev(respiratory_rates)
    fio2_percent_stdev = statistics.stdev(fio2_percentages)
    exhaled_tidal_volumes_stdev = statistics.stdev(exhaled_tidal_volumes)
    exhaled_minute_volumes_stdev = statistics.stdev(exhaled_minute_volumes)
    peeps_stdev = statistics.stdev(peeps)

    print("plateau_pressures_stdev: " + str(plateau_pressures_stdev))
    print("respiratory_rates_stdev: " + str(respiratory_rates_stdev))
    print("fio2_percent_stdev: " + str(fio2_percent_stdev))
    print("exhaled_tidal_volumes_stdev: " + str(exhaled_tidal_volumes_stdev))
    print("exhaled_minute_volumes_stdev: " + str(exhaled_minute_volumes_stdev))
    print("peeps_stdev: " + str(peeps_stdev))

    # Assert variance is below a sensible threshold - this is a
    # 'steady-state' dump file we're asserting so we assume quite a low variance
    coefficient_of_variation = 0.1
    assert plateau_pressures_stdev <= coefficient_of_variation
    assert respiratory_rates_stdev <= coefficient_of_variation
    assert fio2_percent_stdev <= coefficient_of_variation
    assert exhaled_tidal_volumes_stdev <= coefficient_of_variation
    assert exhaled_minute_volumes_stdev <= coefficient_of_variation
    assert peeps_stdev <= coefficient_of_variation
