#!/usr/bin/python3
"""Open files in the editor of the Router Manager's Shell page, from the shell of that page; vre is its short name.

Each file is named to the router's web service over SOCKET with the shell's session,
$VPN_ROUTER_SHELL, which the web service sets in the shells it starts; the Shell page then shows
the file in a tab of its editor, where it is read and saved. The command returns at once. A
relative path is taken from the current directory, and a file that does not exist is created when
it is saved. The exit status is 0 when every file was opened, 1 when the web service refused one,
with its reason, and 2 outside the Router Manager's shell or for an invalid request. -h or --help
shows the usage.

  vre FILE...
"""

import argparse
import json
import os
import socket
import sys

#: The socket of the router's web service that opens files in the editor of a shell.
SOCKET = '/run/vpn-router/editor.sock'

#: Seconds to wait for the web service's answer.
TIMEOUT = 10


class Parser(argparse.ArgumentParser):
    """An argument parser whose errors end with status 2."""

    def error(self, message):
        print(f'{self.prog}: {message}; see {self.prog} --help', file=sys.stderr)
        sys.exit(2)


def opened(session, path):
    """Ask the web service to open the file in the editor of the session; None, or the reason it refused."""
    with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as connection:
        connection.settimeout(TIMEOUT)
        connection.connect(SOCKET)
        connection.sendall(json.dumps({'session': session, 'path': path}).encode() + b'\n')
        answer = json.loads(connection.makefile('rb').readline() or b'{}')
    return None if answer.get('ok') is True else str(answer.get('error', 'no answer'))


def main(argv):
    prog = os.path.basename(sys.argv[0])
    parser = Parser(prog=prog, description="Open files in the editor of the Router Manager's Shell page.")
    parser.add_argument('files', nargs='+', metavar='FILE', help='a file to open')
    options = parser.parse_args(argv)
    session = os.environ.get('VPN_ROUTER_SHELL', '')
    if not session:
        print(f'{prog}: {prog} works only in the shell of the Router Manager', file=sys.stderr)
        return 2
    status = 0
    for name in options.files:
        path = os.path.abspath(os.path.expanduser(name))
        try:
            reason = opened(session, path)
        except (OSError, ValueError) as exc:
            reason = f'the web service cannot be reached: {exc}'
        if reason:
            print(f'{prog}: {path}: {reason}', file=sys.stderr)
            status = 1
        else:
            print(f'Opened {path} in the editor of the Shell page.')
    return status


if __name__ == '__main__':
    sys.exit(main(sys.argv[1:]))
