"""
Util for talking to the client program in order to retrieve
dynamic defaults for the UI
"""
import subprocess
from json import JSONDecodeError
from subprocess import CalledProcessError

from gooey.python_bindings.types import Try, Success, Failure
from gooey.python_bindings.coms import deserialize_inbound


def communicate(cmd, encoding) -> Try:
    """
    Invoke the processes specified by `cmd`.
    Assumes that the process speaks JSON over stdout. Non-json response
    are treated as an error.

    Implementation Note: I don't know why, but `Popen` is like ~5-6x faster
    than `check_output`. in practice, it means waiting for ~1/10th
    of a second rather than ~7/10ths of a second. A
    difference which is pretty weighty when there's a
    user waiting on the other end.
    """
    try:
        proc = subprocess.Popen(
            cmd,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE
        )
        out, err = proc.communicate()
        if out and proc.poll() == 0:
            return Success(deserialize_inbound(out, encoding))
        else:
            return Failure(CalledProcessError(proc.returncode, cmd, output=out, stderr=err))
    except JSONDecodeError as e:
        return Failure(e)

