# command line interface

import os
import sys
import asyncclick as click
from distkv.util import MsgReader
from functools import partial
from distkv.util import MsgReader, MsgWriter

from distkv.util import (
    attrdict,
    PathLongener,
    MsgReader,
    PathShortener,
    split_one,
    NotGiven,
)
from distkv.client import StreamedRequest
from distkv.default import CFG
from distkv.server import Server
from distkv.auth import loader, gen_auth
from distkv.exceptions import ClientError
from distkv.util import yprint

import logging

logger = logging.getLogger(__name__)


@main.group(short_help="Manage data.")
@click.pass_obj
async def cli(obj):
    """
    Low-level tools that don't depend on a running server.
    """
    pass


@cli.command()
@click.argument("path", nargs=-1)
@click.pass_obj
async def cfg(obj, path):
    """Emit the current configuration as a YAML file.
    
    You can limit the output by path elements.
    E.g., "cfg connect host" will print "localhost".

    Single values are printed with a trailing line feed.
    """
    cfg = obj.cfg
    for p in path:
        try:
            cfg = cfg[p]
        except KeyError:
            if obj.debug:
                print("Unknown:",p)
            sys.exit(1)
    if isinstance(cfg,str):
        print(cfg, file=obj.stdout)
    else:
        yprint(cfg, stream=obj.stdout)


@cli.command()
@click.argument("file", nargs=1)
@click.pass_obj
async def file(obj, file):
    """Read a MsgPack file and dump as YAML."""
    async with MsgReader(path=file) as f:
        async for msg in f:
            yprint(msg, stream=obj.stdout)
            print("---", file=obj.stdout)

@cli.command()
@click.argument("node", nargs=1)
@click.argument("file", type=click.Path(), nargs=1)
@click.pass_obj
async def init(obj, node, file):
    """Write an initial preload file.
    
    Usage: distkv dump init <node> <outfile>

    Writes an initial DistKV file that behaves as if it was generated by <node>.

    Using this command, followed by "distkv server -l <outfile> <node>", is
    equivalent to running "distkv server -i 'Initial data' <node>.
    """
    async with MsgWriter(path=file) as f:
        await f(dict(chain=dict(node=node,tick=1,prev=None),depth=0,path=[],tock=1,value="Initial data"))

@cli.command()
@click.pass_obj
async def serf(obj):
    """Monitor the Serf messafge stream.
    """
    from asyncserf import NoopCodec, serf_client
    import msgpack

    async with serf_client(codec=NoopCodec(), **obj.cfg.server.serf) as client:  # pylint: disable=not-async-context-manager
        async with client.stream("*") as stream:
            async for resp in stream:
                c=vars(resp)
                c.pop('client', None)
                c.pop('coalesce', None)
                p=c['payload']
                if c.get('event','').startswith('member-'):
                    m = partial(msgpack.unpackb,raw=True, use_list=False)
                    p = m(p)
                else:
                    m = partial(msgpack.unpackb,raw=False, use_list=False)
                    p = m(p)
                c['payload'] = p

                yprint(c)
                print("---")


if __name__ == "__main__":
    logging.basicConfig(level=logging.DEBUG)
    anyio.run(main)

