import argparse
import boto
from os.path import basename
from time import sleep

FAILURE_STATES = [
    'CREATE_FAILED',
    'ROLLBACK_IN_PROGRESS',
    'ROLLBACK_FAILED',
    'ROLLBACK_COMPLETE',
    'DELETE_IN_PROGRESS',
    'DELETE_FAILED',
    'DELETE_COMPLETE',
    ]

def upload_file(file_path, bucket_name, key_name):
    """
    Upload a file to the given s3 bucket and return a template url.
    """
    conn = boto.connect_s3()
    try:
        bucket = conn.get_bucket(bucket_name)
    except boto.exception.S3ResponseError as e:
        conn.create_bucket(bucket_name)
        bucket = conn.get_bucket(bucket_name, validate=False)

    key = boto.s3.key.Key(bucket)
    key.key = key_name 
    key.set_contents_from_filename(file_path)

    url = 'https://s3.amazonaws.com/{}/{}'.format(bucket_name, key_name)
    return url

def create_stack(stack_name, template, region='us-east-1', blocking=True, temp_bucket='edx-sandbox-devops'):
    cfn = boto.connect_cloudformation()

    # Upload the template to s3
    key_name = 'cloudformation/auto/{}_{}'.format(stack_name, basename(template))
    template_url = upload_file(template, temp_bucket, key_name)

    # Reference the stack.
    try:
        stack_id = cfn.create_stack(stack_name,
            template_url=template_url,
            capabilities=['CAPABILITY_IAM'],
            tags={'autostack':'true'},
            parameters=[('KeyName', 'continuous-integration')])
    except Exception as e:
        print(e.message)
        raise e

   
    status = None 
    while blocking:
        sleep(5)
        stack_instance = cfn.describe_stacks(stack_id)[0]
        status = stack_instance.stack_status
        print(status)
        if 'COMPLETE' in status:
            break

    if status in FAILURE_STATES:
        raise Exception('Creation Failed. Stack Status: {}, ID:{}'.format(
            status, stack_id))

    return stack_id


if __name__ == '__main__':
        description = 'Create a cloudformation stack from a template.'
        parser = argparse.ArgumentParser(description=description)

        msg = 'Name for the cloudformation stack.'
        parser.add_argument('-n', '--stackname', required=True, help=msg)

        msg = 'Name of the bucket to use for temporarily uploading the \
            template.'
        parser.add_argument('-b', '--bucketname', default="edx-sandbox-devops",
            help=msg)

        msg = 'The path to the cloudformation template.'
        parser.add_argument('-t', '--template', required=True, help=msg)
       
        msg = 'The AWS region to build this stack in.'
        parser.add_argument('-r', '--region', default='us-east-1', help=msg)
       
        args = parser.parse_args() 
        stack_name = args.stackname
        template = args.template
        region = args.region
        bucket_name = args.bucketname

        create_stack(stack_name, template, region, bucket_name)
        print('Stack({}) created.'.format(stack_name))