#!/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):
    """
    Return the jumphost url with HTTP scheme if we're in testing mode,
    HTTPS otherwise.
    """
    if config['password_provider'] == 'testing':
        return 'http://' + config.jump_host
    return 'https://' + 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-url',
              metavar='<auth_url>',
              help="Auth-server URL.")
@click.option('-s', '--client-secret',
              metavar='<secret>',
              help='Special client secret, ask mum.')
@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)
    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.json().get("error")))
        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!")


if __name__ == '__main__':
    try:
        main()
    except Exception as e:
        log.info(e)
        if log.VERBOSE:
            raise
        else:
            sys.exit(1)
