# command line interface

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 MsgReader
from distkv.util import yprint

import logging

logger = logging.getLogger(__name__)


@main.group(short_help="Manage data.")  # pylint: disable=undefined-variable
@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 message 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("---")
