import datetime
import os

import boto3

__all__ = [
    'ec2_instance_attributes',
    'export_name_bindings_to_file',
    'export_name_bindings_to_environment',
    'rebind_all',
    'get_ec2_name_bindings',
    'AWS_CONFIG_FILE'
]

# Constants

# Locations
AWS_CONFIG_DIR = os.path.expanduser('~/.ec2x')
AWS_CONFIG_FILE = os.path.expanduser(AWS_CONFIG_DIR + '/name_bindings')


# Public interface
def ec2_instance_attributes():
    ec2 = boto3.resource('ec2')
    return \
        [
            {
                'name': _get_tag_value(instance, 'Name'),
                'public_dns_name': instance.public_dns_name,
                'id': instance.id

            }
            for instance in ec2.instances.all()
            ]


def get_ec2_name_bindings():
    bindings = {}
    for instance in ec2_instance_attributes():
        bindings[instance['name']] = instance['public_dns_name']
        bindings[instance['name'] + '_id'] = instance['id']
    return bindings


def export_name_bindings_to_file():
    with _open_aws_env_file('w') as name_binding:
        _write_file_header(name_binding)
        for key, value in sorted(iter(get_ec2_name_bindings().items())):
            name_binding.write('export ' + key.replace('-', '_') + '=' + value + '\n')


def export_name_bindings_to_environment():
    for key, value in iter(get_ec2_name_bindings().items()):
        os.environ[key] = value


def rebind_all():
    export_name_bindings_to_file()
    export_name_bindings_to_environment()


# Private implementation

def _get_tag_value(ec2_instance, tag_name):
    if ec2_instance.tags:
        value = None
        for kv_pair in ec2_instance.tags:
            if kv_pair['Key'] == tag_name:
                value = kv_pair['Value']
        return value


def _open_aws_env_file(mode):
    if not os.path.exists(AWS_CONFIG_DIR):
        os.mkdir(AWS_CONFIG_DIR)
    return open(AWS_CONFIG_FILE, mode)


def _write_file_header(f):
    f.write("####\n#   AWS Name Binding File\n#   Generated by aws_utils.name_binding.py at: " + str(
        datetime.datetime.now()) + "\n####\n\n")
