# command line interface  # noqa: D100
from __future__ import annotations

import asyncclick as click

from moat.util import yprint
from moat.lib.path import P
from moat.lib.run import attr_args, process_args
from moat.link.client import Link

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from moat.lib.rpc import MsgSender


@click.command(short_help="Send a command")
@click.option("-S", "--stream", is_flag=True, help="Read a stream")
@click.option("-R", "--raw", is_flag=True, help="Show raw message data")
@click.option("-C", "--client", type=P, help="Connect to this client")
@click.argument("path", type=P, nargs=1)
@click.pass_context
@attr_args(with_path=True, with_arglist=True)
async def cli(ctx, path, stream, raw, client, **kw):
    """
    Send a command to the server.
    """
    obj = ctx.obj
    cfg = obj.cfg["link"]
    if obj.get("port", None) is not None:
        cfg.client.port = obj.port

    async with Link(cfg) as conn:
        svc: MsgSender = await conn.get_service(client) if client else conn.sender

        kw = process_args({None: []}, no_path=True, **kw)
        args = kw.pop(None)
        if stream:
            async with svc.cmd(path, *args, **kw).stream_in() as res:
                yprint(rep_(res, raw), stream=obj.stdout)
                print("---", file=obj.stdout)
                async for msg in res:
                    yprint(rep_(msg, raw), stream=obj.stdout)
                    print("---", file=obj.stdout)
        else:
            res = await svc.cmd(path, *args, **kw)
        yprint(rep_(res, raw), stream=obj.stdout)


def rep_(res, raw=False):  # noqa: D103
    if raw:
        return res.args + [res.kw]
    if not res.args:
        return res.kw
    if res.kw:
        return res.args + [res.kw]
    if len(res.args) == 1:
        return res.args[0]
    return res.args
