#!/usr/bin/env python
import json
import os
import sys
import pprint

import cbas.log as log
import click
import requests
from cbas import __version__
from cbas.auth_server import obtain_access_token
from cbas.configuration import (DEFAULT_CONFIG_PATH, CBASConfig,
                                MissingConfigValues, UnexpectedConfigValues,
                                pass_config)
from cbas.log import info
from cbas.password_providers import get_password


pp = pprint.PrettyPrinter(indent=1)


def get_sshkey(ssh_key_file):
    with open(os.path.expanduser(ssh_key_file), "r") as f:
        return f.read()


def get_jump_url(config):
    if "://" in config.jump_host:
        return config.jump_host
    else:
        return 'https://{0}'.format(config.jump_host)


def print_version(ctx, param, value):
    if not value or ctx.resilient_parsing:
        return
    click.echo('cbas version: {0}'.format(__version__))
    ctx.exit()


def process_verbose(ctx, param, value):
    log.VERBOSE = value


def read_wrapper(ctx, param, value):
    return CBASConfig.read(ctx, param, value)


@click.group()
@click.option('-v', '--verbose',
              is_flag=True,
              expose_value=False,
              callback=process_verbose,
              help="Activate verbose mode."
              )
@click.option('-c', '--config',
              type=click.Path(exists=False, file_okay=True, dir_okay=True),
              callback=read_wrapper,
              help="Path to config file. Default: '~/.cbas'.",
              metavar='<config_path>',
              default=DEFAULT_CONFIG_PATH,
              )
@click.option('-u', '--username',
              metavar='<username>',
              help="Username. Default: the logged in user.")
@click.option('-k', '--ssh-key-file',
              metavar='<key-file>',
              help="SSH Identity to use. Default: '~/.ssh/id_rsa.pub'.")
@click.option('-p', '--password-provider',
              metavar='<provider>',
              help="Password provider. Default: 'prompt'.")
@click.option('-a', '--auth-host',
              metavar='<host>',
              help="Auth-server host.")
@click.option('-h', '--jump-host',
              metavar='<host>',
              help="Jump host to connect with.")
@click.option('--version',
              is_flag=True,
              expose_value=False,
              is_eager=True,
              callback=print_version,
              help="Print version and exit.")
def main(config, **kwargs):
    log.verbose('Values supplied on the command-line are:')
    log.verbose(pp.pformat(kwargs))
    config.inject(kwargs)
    log.verbose('Final aggregated config:')
    log.verbose(str(config))
    config.is_complete()


@main.command(help="Upload ssh-key and create user.")
@pass_config
def upload(config):
    ssh_key = get_sshkey(config.ssh_key_file)
    password = get_password(config.password_provider, config.username)
    access_token = obtain_access_token(config, password)

    jump_request_header = {'Authorization': 'Bearer ' + access_token,
                           'Content-Type': 'application/json',
                           'Cache-Control': 'no-cache'}
    jump_request_data = json.dumps({"pubkey": ssh_key})
    jump_url = get_jump_url(config) + '/create'
    info("Will now attempt to upload your ssh-key...")
    jump_response = requests.post(jump_url,
                                  jump_request_data,
                                  headers=jump_request_header)
    if jump_response.status_code not in [200, 201]:
        log.info("Upload failed: {0}".  format(jump_response.text))
        jump_response.raise_for_status()
    else:
        log.info("Upload OK!")


@main.command(help="Delete user.")
@pass_config
def delete(config):
    password = get_password(config.password_provider, config.username)
    access_token = obtain_access_token(config, password)

    jump_request_header = {'Authorization': 'Bearer ' + access_token,
                           'Content-Type': 'application/json',
                           'Cache-Control': 'no-cache'}
    jump_url = get_jump_url(config) + '/delete'

    info("Will now attempt to delete your user...")
    jump_response = requests.post(jump_url, headers=jump_request_header)
    if jump_response.status_code != 200:
        log.info("Delete failed!")
        jump_response.raise_for_status()
    else:
        log.info("Delete OK!")


@main.command(help="Dry run, sanitize all config only.")
@pass_config
def dry_run(config):
    pass


if __name__ == '__main__':
    try:
        main()
    except (MissingConfigValues, UnexpectedConfigValues) as e:
        log.info("ERROR: {0}".format(e))
        sys.exit(1)
    except Exception as e:
        log.info(e)
        if log.VERBOSE:
            raise
        else:
            sys.exit(1)
