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

import click
import requests

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


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):
    try:
        return CBASConfig.read(ctx, param, value)
    except UnexpectedConfigValues as e:
        raise CMDLineExit(e)


@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.',
              metavar='<config_path>',
              default=DEFAULT_CONFIG_PATH,
              )
@click.option('-u', '--username',
              metavar='<username>',
              help="Username.")
@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('-p', '--password-provider',
              metavar='<provider>',
              help="Password provider.")
@click.option('-h', '--jump-host',
              metavar='<host>',
              help="Jump host to connect with.")
@click.option('-k', '--ssh-key-file',
              metavar='<key-file>',
              help='SSH Identity to use.')
@click.option('--version',
              is_flag=True,
              expose_value=False,
              is_eager=True,
              callback=print_version,
              help="Print version and exit.")
def main(config, **kwargs):
    config.inject(kwargs)
    try:
        config.is_complete()
    except MissingConfigValues as e:
        raise CMDLineExit(e)


@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")))
        if log.VERBOSE:
            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:
        if log.VERBOSE:
            jump_response.raise_for_status()
        log.info("Delete failed!")
    else:
        log.info("Delete OK!")


if __name__ == '__main__':
    try:
        main()
    except CMDLineExit as e:
        log.info(e)
        if log.VERBOSE:
            raise
