"""ecFlow hooks"""

import logging
import pathlib

from .. import InvocationError
from ..connection import PIPE
from ..connections.local import LocalConnection
from ..connections.local import LocalConnection
from ..parser import DirectiveParser
from ..utils import check_retcode

_logger = logging.getLogger(__name__)


def abort_on_ecflow(site, script, jid, cancel_status, dryrun=False):
    """Post-kill hook to issue an abort on behalf of a job that was killed
    or cancelled without the opportunity to inform ecFlow itself."""
    if cancel_status == 'CANCELLED':
        msg = 'Cancelled before starting'
    elif cancel_status == 'KILLED':
        msg = 'Killed forcefully'
    elif cancel_status == 'VANISHED':
        msg = 'Vanished unexpectedly'
    elif cancel_status == 'TERMINATED':
        return
    else:
        raise InvocationError(f'abort_on_ecflow: unknown cancel status "{cancel_status}"')

    script = pathlib.Path(script)
    orig_script = script.with_suffix(script.suffix + ".orig")

    parser = DirectiveParser()
    with open(orig_script, 'rb') as sin:
        for line in sin:
            parser.feed(line)
    env = {}
    for (directive, var, required) in [
        ('ecflow_name', 'ECF_NAME', True),
        ('ecflow_pass', 'ECF_PASS', True),
        ('ecflow_host', 'ECF_HOST', False),
        ('ecflow_port', 'ECF_PORT', False),
        ]:
        try:
            env[var] = parser.data[directive].decode('ascii')
        except KeyError:
            if required:
                _logger.error(f'abort_on_ecflow could not find {directive} defined in script {script}')
                raise

    cmd = [ parser.data.get('ecflow_client', 'ecflow_client'), f'--abort={msg}' ]

    if site._connection.is_local():
        _logger.debug(f'abort_on_ecflow running {" ".join(cmd)} on local site with env {env!r}')
        connection = site._connection
    elif 'ecflow_host' in env:
        _logger.debug(f'abort_on_ecflow running {" ".join(cmd)} on remote site with env {env!r}')
        connection = site._connection
    else:
        _logger.debug(f'abort_on_ecflow running {" ".join(cmd)} locally with env {env!r}')
        connection = LocalConnection({}, site._connection.user)

    proc = connection.execute(cmd, stdout=PIPE, stderr=PIPE, env=env, dryrun=dryrun)
    if dryrun:
        return

    proc_stdout, proc_stderr = proc.communicate()
    retcode = proc.returncode
    if proc.returncode != 0:
        if proc_stdout: _logger.error("ecflow_client stdout for script %s:\n%s", script, proc_stdout.strip())
        if proc_stderr: _logger.error("ecflow_client stderr for script %s:\n%s", script, proc_stderr.strip())
        check_retcode(proc.returncode, what="Abort")
    else:
        if proc_stdout: _logger.debug("ecflow_client stdout for script %s:\n%s", script, proc_stdout.strip())
        if proc_stderr: _logger.debug("ecflow_client stderr for script %s:\n%s", script, proc_stderr.strip())
