import csv
import io

import click

from .utils import client, output
from ..constants import NL_OK
from ..errors.common import NetlabError
from ..serializer import serialize


@click.command()
@click.pass_context
@click.argument('method', nargs=1)
@click.argument('arguments', nargs=-1)
@click.option('--system', default='default', help="NETLAB+ system to communicate with.")
@click.option('--output', 'output_type', default='table', help="Change the output format. "
                                                               "[table, csv, tsv, json, var] ")
def api(ctx, method, arguments, system, output_type):
    """ Communicate with a remote NETLAB+ server API"""
    try:
        api_method = getattr(client(system), method)
    except AttributeError:
        api_method = None
        click.echo("{} is not a valid API method. Please check the documentation.".format(
            click.style(method, fg='red')))
        ctx.exit(1)

    api_arguments = {}
    try:
        for arg in arguments:
            key, value = arg.split('=')
            api_arguments[key.lower()] = value
    except ValueError:
        # user probably didn't pass arguments in the key=value format
        click.secho("There is an error with your method arguments.", fg='red')
        click.secho("Please ensure they are in the format of arg=value. \n\nExample:")
        click.secho("    {} user_account_get acc_id=100001".format(ctx.command_path), fg='cyan')
        ctx.exit(1)

    try:
        results = api_method(**api_arguments)
    except (TypeError, NetlabError) as err:
        results = None
        click.secho("{}: {}".format(type(err).__name__, err), fg='red')
        click.echo("Please check the documentation for help.")
        ctx.exit(1)

    if results == NL_OK:
        click.secho("Success!", fg='green')
    elif isinstance(results, int) or isinstance(results, str):
        click.echo(results)
    else:
        outputs = {
            'table': table_output,
            'csv': csv_output,
            'tsv': tsv_output,
            'json': json_output,
            'var': var_output
        }
        outputs[output_type](results)


def table_output(results):
    if isinstance(results, dict):
        results = [results]
    output(results, headers='keys')


def csv_output(results, delimiter=','):
    out = io.StringIO()

    if isinstance(results, dict):
        results = [results]

    fieldnames = list(results[0].keys())

    writer = csv.DictWriter(out, fieldnames=fieldnames, quoting=csv.QUOTE_MINIMAL, delimiter=delimiter)
    writer.writeheader()
    for result in results:
        writer.writerow(result)
    click.echo(out.getvalue())


def tsv_output(results):
    csv_output(results, delimiter='\t')


def json_output(results):
    click.echo(serialize(results, pretty=True))


def var_output(results):
    if isinstance(results, dict):
        results = [results]

    out = []
    for result in results:
        row = ""
        for key, value in result.items():
            row += "{}={} ".format(key, value)
        out.append(row)
    click.echo("\n".join(out))
