import pythonmidas.pythonmidas as Midas
import subprocess as sp


def read_ppg(filename="/home/mpet/online/ppg/ppgload/delays.dat"):
    """
    Read the file "delays.dat". This is generated by tri_config, and
    contains all of the offsets for the different pulses in the ppg
    cycle in a human readable form.

    We seach the file for the strings "BEGIN_SCAN" and "END_SCAN" to
    get the offsets, from which it is easy to calcalute the run time.

    This ignores any transitions that occur before the begin_scan
    variable in the ppg cycle. Generally, there are only a few
    milliseconds of time there, so we can ignore it.
    """
    data = None
    with open(filename) as file:
        data = file.readlines()

    beginscan = [x for x in data if x.find("BEGIN_SCAN") > -1]
    endscan = [x for x in data if x.find("END_SCAN") > -1]

    begintime = beginscan[0].split()[4]
    endtime = endscan[0].split()[4]

    # the number of loop scans is also contained in the delays.dat file,
    # so let's get it
    numscans = beginscan[0].split()[6]

    # Return number of seconds
    return float(numscans) * (float(endtime) - float(begintime)) / 1000.0


def run_time():
    """
    Return the runtime in minutes. This is useful for calculating
    how long a tune switch will run for.
    """
    triconfig()  # ODB might have updated, so recompile the ppg
    try:
        return "{0:.2f}".format(read_ppg() / 60.0)
    except:
        raise Exception("Couldn't find begin_scan or end_scan. " +
                        "Check ppg names.")


def triconfig():
    """
    Run the triconfig command to recompile the ppg with the
    current odb settings.

    If the run is stopped, tri_config will run to update the
    "delays.data" file with the current entries in the ODB. This
    is useful if you want to see how long a run will take, e.g.
    how long will a run take before I start this TuneSwitch?

    If the run is not stopped, then it will not recompile the PPG,
    as it may interfer with the current run. Instead, it will
    calculate the run time based on the "delays.dat" generated
    when the run started.

    If the tri_config exits with an error, an exception will be
    raised. This should only happen if there's a problem with the
    ppg settings (transitions occuring after the end_ramp are the
    most common), or if there is a problem communicating with the
    softdac or ppg hardware.
    """

    # only run tri_config if the run is stopped
    if check_run_state() == "stopped":
        shell = sp.Popen("ssh mpet@lxmpet.triumf.ca " +
                         "\"/home/mpet/online/tri_config -s\"",
                         shell=True,
                         stdout=sp.PIPE,
                         stderr=sp.PIPE)
        shell.communicate()
        #print shell.returncode
        if shell.returncode > 1 or shell.returncode < 0:
            raise Exception("tri_config compile error")


def check_run_state():
    """
    Check the run state.
    """
    path = "/Runinfo/State"
    state = int(Midas.varget(path))

    if state == 1:
        return "stopped"
    if state == 2:
        return "paused"
    if state == 3:
        return "running"

    # should never get here, but return "running" so that we don't
    # mess anything up.
    return "running"
