#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
cli.py

The module that implements the CLI for obis.


Created by Chandrasekhar Ramakrishnan on 2017-01-27.
Copyright (c) 2017 Chandrasekhar Ramakrishnan. All rights reserved.
"""
import json
from datetime import datetime

import click

from .. import dm
from ..dm.command_result import CommandResult
from ..dm.utils import cd


def click_echo(message):
    timestamp = datetime.now().strftime("%H:%M:%S")
    click.echo("{} {}".format(timestamp, message))


def click_progress(progress_data):
    if progress_data['type'] == 'progress':
        click_echo(progress_data['message'])


def click_progress_no_ts(progress_data):
    if progress_data['type'] == 'progress':
        click.echo("{}".format(progress_data['message']))


def shared_data_mgmt(context={}):
    git_config = {'find_git': True}
    openbis_config = {}
    if context.get('verify_certificates') is not None:
        openbis_config['verify_certificates'] = context['verify_certificates']
    return dm.DataMgmt(openbis_config=openbis_config, git_config=git_config)


def check_result(command, result):
    if result.failure():
        click_echo("Could not {}:\n{}".format(command, result.output))
    return result.returncode


@click.group()
@click.option('-q', '--quiet', default=False, is_flag=True, help='Suppress status reporting.')
@click.option('-s', '--skip_verification', default=False, is_flag=True, help='Do not verify cerficiates')
@click.pass_context
def cli(ctx, quiet, skip_verification):
    ctx.obj['quiet'] = quiet
    if skip_verification:
        ctx.obj['verify_certificates'] = False


@cli.command()
@click.pass_context
@click.argument('repository', type=click.Path(exists=True))
def addref(ctx, repository):
    """Add a reference to the other repository in this repository.
    """
    with cd(repository):
        data_mgmt = shared_data_mgmt(ctx.obj)
        return check_result("addref", data_mgmt.addref())


@cli.command()
@click.pass_context
@click.option('-u', '--ssh_user', default=None, help='User to connect to remote systems via ssh')
@click.option('-c', '--content_copy_index', type=int, default=None, help='Index of the content copy to clone from in case there are multiple copies')
@click.argument('data_set_id')
def clone(ctx, ssh_user, content_copy_index, data_set_id):
    """Clone the repository found in the given data set id.
    """
    data_mgmt = shared_data_mgmt(ctx.obj)
    return check_result("clone", data_mgmt.clone(data_set_id, ssh_user, content_copy_index))


@cli.command()
@click.pass_context
@click.option('-m', '--msg', prompt=True, help='A message explaining what was done.')
@click.option('-a', '--auto_add', default=True, is_flag=True, help='Automatically add all untracked files.')
def commit(ctx, msg, auto_add):
    """Commit the repository to git and inform openBIS.
    """
    data_mgmt = shared_data_mgmt(ctx.obj)
    return check_result("commit", data_mgmt.commit(msg, auto_add))


@cli.command()
@click.option('-g', '--is_global', default=False, is_flag=True, help='Configure global or local.')
@click.argument('prop', default="")
@click.argument('value', default="")
@click.pass_context
def config(ctx, is_global, prop, value):
    """Configure the openBIS setup.

    Configure the openBIS server url, the data set type, and the data set properties.
    """
    data_mgmt = shared_data_mgmt(ctx.obj)
    resolver = data_mgmt.config_resolver
    if is_global:
        resolver.location_search_order = ['global']
    else:
        top_level_path = data_mgmt.git_wrapper.git_top_level_path()
        if top_level_path.success():
            resolver.location_resolver.location_roots['data_set'] = top_level_path.output
            resolver.location_search_order = ['local']
        else:
            resolver.location_search_order = ['global']

    config_dict = resolver.config_dict()
    if not prop:
        config_str = json.dumps(config_dict, indent=4, sort_keys=True)
        click.echo("{}".format(config_str))
    elif not value:
        little_dict = {prop: config_dict[prop]}
        config_str = json.dumps(little_dict, indent=4, sort_keys=True)
        click.echo("{}".format(config_str))
    else:
        return check_result("config", set_property(data_mgmt, prop, value, is_global))


def set_property(data_mgmt, prop, value, is_global):
    """Helper function to implement the property setting semantics."""
    loc = 'global' if is_global else 'local'
    resolver = data_mgmt.config_resolver
    resolver.set_value_for_parameter(prop, value, loc)
    if not is_global:
        return data_mgmt.commit_metadata_updates(prop)
    else:
        return CommandResult(returncode=0, output="")


def init_data_impl(ctx, sample_id, experiment_id, folder, name):
    """Shared implementation for the init_data command."""
    click_echo("init_data {}".format(folder))
    data_mgmt = shared_data_mgmt(ctx.obj)
    name = name if name != "" else None
    result = data_mgmt.init_data(folder, name, create=True)
    if (not sample_id and not experiment_id) or result.failure():
        return check_result("init_data", result)
    with dm.cd(folder):
        if sample_id:
            return check_result("init_data", set_property(data_mgmt, 'sample_id', sample_id, False))
        if experiment_id:
            return check_result("init_data", set_property(data_mgmt, 'experiment_id', experiment_id, False))


@cli.command()
@click.pass_context
@click.option('-si', '--sample_id', help='Set the id of the owning sample.')
@click.option('-ei', '--experiment_id', help='Set the id of the owning experiment.')
@click.argument('folder', type=click.Path(exists=False, file_okay=False))
@click.argument('name', default="")
def init(ctx, sample_id, experiment_id, folder, name):
    """Initialize the folder as a data folder (alias for init_data)."""
    return init_data_impl(ctx, sample_id, experiment_id, folder, name)


@cli.command()
@click.pass_context
@click.option('-si', '--sample_id', help='Set the id of the owning sample.')
@click.option('-ei', '--experiment_id', help='Set the id of the owning experiment.')
@click.argument('folder', type=click.Path(exists=False, file_okay=False))
@click.argument('name', default="")
def init_data(ctx, sample_id, experiment_id, folder, name):
    """Initialize the folder as a data folder."""
    return init_data_impl(ctx, sample_id, experiment_id, folder, name)


@cli.command()
@click.pass_context
@click.argument('folder', type=click.Path(exists=False, file_okay=False))
def init_analysis(ctx, folder):
    """Initialize the folder as an analysis folder."""
    click_echo("init analysis {}".format(folder))


@cli.command()
@click.pass_context
@click.argument('file')
def get(ctx, f):
    """Get one or more files from a clone of this repository.
    """
    click_echo("get {}".format(f))


@cli.command()
@click.pass_context
def status(ctx):
    """Sync the repository with openBIS.
    """
    data_mgmt = shared_data_mgmt(ctx.obj)
    result = data_mgmt.status()
    click.echo(result.output)


@cli.command()
@click.pass_context
def sync(ctx):
    """Sync the repository with openBIS.
    """
    data_mgmt = shared_data_mgmt(ctx.obj)
    return check_result("sync", data_mgmt.sync())


def main():
    cli(obj={})


if __name__ == '__main__':
    main()