"""
Utils for integration tests.
Includes functions to start and kill the background ArduinoEmulator
and hevserver scripts and manage them from within code, rather than
using the CLI. Nothing wrong with using CLI, but managing these
processes from within test-code itself is useful for testing
can be more atomic and easier to manage: consider starting/killing
the background processes for each/every test individually and/or once
for a particular test-suite.
"""
import os
import time
import signal
from pathlib import Path
from subprocess import Popen
import pytest


def start_background_arduinosim_hevserver() -> [Popen]:
    """Start the ArduinoEmulator.pt and Hevserver.py and return a
    Popen that represents a *nix process group. The process-group.pid is
    a linux session id that can be used to kill spawned child processes
    started by the arduino and hevserver."""

    pythonpath_val = os.path.expandvars("$PYTHONPATH")
    myenv = {"PYTHONPATH": pythonpath_val}
    pypath = Path(pythonpath_val)
    proj_root_path = str(pypath.parent.absolute())
    procs = []

    # Run with preexec_fn=os.setid. Is run after fork() but before exec() to get a sessionId for
    # killing child procs spawned off shell (means SIGTERMing the parent shell SIGTERMs children)
    # B6-20201207.dump
    process1 = Popen(
        """
        { . ./.hev_env/bin/activate ;
         cd ./raspberry-dataserver ;
         ./ArduinoEmulator.py -f ./share/FromDerick.dump &
         ./hevserver.py --use-dump-data &
         }
        """,
        cwd=proj_root_path,
        shell=True,
        env=myenv,
        # stderr=subprocess.PIPE, stdout=subprocess.PIPE, # don't use in our case - overrides capsys
        text=True,
        preexec_fn=os.setsid,
    )
    procs.append(process1)

    time.sleep(2)  # give enough time for scripts to generate stderr/out
    return procs


def kill_process_group(pid: int):
    """Safely SIGTERM the process group with the given id"""
    if pid is not None and pid > 0:
        os.killpg(os.getpgid(pid), signal.SIGTERM)


def assert_posix():
    """Assert the test platform is posix based"""
    assert os.name == "posix"


def assert_pythonpath():
    """Assert the PYTHONPATH env var has been set"""
    pythonpath_key = "$PYTHONPATH"
    pythonpath_val = os.path.expandvars(pythonpath_key)
    if pythonpath_val == pythonpath_key:
        pytest.fail(msg="Please set the $PYTHONPATH env var")
