#!/L/python 3.6
from lgtm.LGTMError import LGTMError
from lgtm.LGTMSocket import LGTMSocket
from typing import List

import os
import socket
import sys


def commit64(msg: bytes) -> bytes:
    """
    Use :param:`msg` as a git commit message, if there are any changes to the
    repository at the end of the current run.

    @returns The full `OK` message.  Otherwise, raises an LGTMError with the
             server's response.
    """
    # Simple heuristic, but catches most of the silly mistakes.
    if b" " in msg or not isinstance(msg, bytes):
        raise ValueError(f"Message {msg!r} is not valid b64.")
    sock: socket.socket
    with LGTMSocket() as sock:
        sock.send(b"COMMIT64 %s\n" % (msg,))
        r: List[bytes] = []
        while True:
            # Read response until newline
            c: bytes = sock.recv(1)
            if len(c) == 0 or not isinstance(c, bytes):
                raise RuntimeError("Unclean remote socket shutdown by LGTM IPCd.")
            r.append(c)
            if c == b"\n":
                break
        response: bytes = b"".join(r)
        if response == b"OK" or response.startswith(b"OK "):
            return response
        # ERR, NO, or just something from outer space.
        raise LGTMError(response)


def main() -> int:
    if not sys.argv or len(sys.argv) != 2 or not sys.argv[1]:
        print(
            f"{sys.argv[0]}: A (single) b64-encoded commit message is required.",
            file=sys.stderr,
        )
        return 2

    msg: bytes = os.fsencode(sys.argv[1])

    try:
        commit64(msg)
    except LGTMError as e:
        e_msg = str(e)
        if isinstance(e_msg, bytes) and e_msg.startswith((b"NO", b"NO ")):
            print(e_msg.decode("ascii", "xmlcharrefreplace"), file=sys.stderr)
            return 3
        if isinstance(e_msg, bytes) and e_msg.startswith((b"ERR", b"ERR ")):
            print(e_msg.decode("ascii", "xmlcharrefreplace"), file=sys.stderr)
            return 4
        print(repr(e), file=sys.stderr)
        return 5

    return 0


if __name__ == "__main__":
    sys.exit(main())
