#!/usr/bin/python

import sys
import boto
import click
import logging
from cfn_sphere.util import convert_file, get_logger, get_message_from_boto_server_error, convert_dict_to_json_string
from cfn_sphere.config import Config
from cfn_sphere.main import StackActionHandler
from cfn_sphere.exceptions import CfnSphereException
from cfn_sphere.aws.cloudformation.template import CloudFormationTemplate
from cfn_sphere.aws.cloudformation.template_loader import CloudFormationTemplateLoader
from cfn_sphere.aws.cloudformation.template_transformer import CloudFormationTemplateTransformer
from boto.exception import NoAuthHandlerFound, BotoServerError

LOGGER = get_logger(root=True)
logging.getLogger('boto').setLevel(logging.FATAL)


def get_current_account_alias():
    try:
        return boto.connect_iam().get_account_alias().account_aliases[0]
    except NoAuthHandlerFound as e:
        click.echo("Authentication error! Please check credentials: {0}".format(e))
        sys.exit(1)
    except BotoServerError as e:
        message = get_message_from_boto_server_error(e)
        click.echo("AWS API Error: {0}".format(message))
        sys.exit(1)
    except Exception as e:
        click.echo("Unknown error occurred loading users account alias: {0}".format(e))
        sys.exit(1)


@click.group(help="This tool manages AWS CloudFormation templates "
                  "and stacks by providing an application scope and useful tooling.")
def cli():
    pass


@cli.command(help="Sync AWS resources with definition file")
@click.argument('filename', type=click.Path(exists=True))
@click.option('--debug', is_flag=True, default=False, help="Debug output")
@click.option('--confirm', is_flag=True, default=False, help="Override user confirm dialog with yes")
def sync(filename, debug, confirm):
    if debug:
        LOGGER.setLevel(logging.DEBUG)
    else:
        LOGGER.setLevel(logging.INFO)

    if confirm or click.confirm(
            'This action will modify AWS infrastructure in account: {0}\nAre you sure?'.format(
                get_current_account_alias()), abort=True):
        try:

            config = Config(filename)
            StackActionHandler(config).create_or_update_stacks()
        except CfnSphereException as e:
            LOGGER.error("Failed, {0}".format(e))
            sys.exit(1)
        except Exception as e:
            LOGGER.error("Failed with unexpected error".format(e))
            LOGGER.exception(e)
            sys.exit(1)


@cli.command(help="Convert JSON to YAML or vice versa")
@click.argument('filename', type=click.Path(exists=True))
@click.option('--debug', is_flag=True, default=False, help="Debug output")
def convert(filename, debug):
    if debug:
        LOGGER.setLevel(logging.DEBUG)

    try:
        click.echo(convert_file(filename))
    except Exception as e:
        LOGGER.error("Error converting {0}:".format(filename))
        LOGGER.exception(e)
        sys.exit(1)


@cli.command(help="Render template as it would be used to create/update a stack")
@click.argument('filename', type=click.Path(exists=True))
def render_template(filename):
    loader = CloudFormationTemplateLoader()
    template = loader.get_template_from_url(filename, None)
    template = CloudFormationTemplateTransformer.transform_template(template)
    click.echo(convert_dict_to_json_string(template.body_dict))


if __name__ == '__main__':
    cli()
