from aardvark import create_app, db
from aardvark.updater import update_account
from swag_client.swag import get_all_accounts
from tqdm import tqdm
from bunch import Bunch
from flask_script import Manager, Command, Option
from gunicorn.config import make_settings
import better_exceptions


manager = Manager(create_app)


@manager.command
def drop_db():
    """ Drops the database. """
    db.drop_all()


@manager.command
def create_db():
    """ Creates the database. """
    from aardvark.model import AWSIAMObject, AdvisorData
    db.create_all()


@manager.command
def config():
    """
    Creates a config file.

    SWAG_BUCKET = '...'
    ROLENAME = 'SecurityMonkey'
    SQLALCHEMY_DATABASE_URI = 'postgresql://user:pass@localhost:5432/db'
    SQLALCHEMY_DATABASE_URI = 'sqlite:///tmp/aardvark.db'
    PHANTOMJS = '/usr/local/bin/phantomjs'
    """
    bucket = raw_input('SWAG_BUCKET: ')
    role_name = raw_input('ROLENAME: ')
    db_uri = raw_input('DATABASE: ')
    phantom = raw_input('Path to phantomjs: ')

    log = """LOG_CFG = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'standard': {
            'format': '%(asctime)s %(levelname)s: %(message)s '
                '[in %(pathname)s:%(lineno)d]'
        }
    },
    'handlers': {
        'file': {
            'class': 'logging.handlers.RotatingFileHandler',
            'level': 'DEBUG',
            'formatter': 'standard',
            'filename': 'aardvark.log',
            'maxBytes': 10485760,
            'backupCount': 100,
            'encoding': 'utf8'
        },
        'console': {
            'class': 'logging.StreamHandler',
            'level': 'DEBUG',
            'formatter': 'standard',
            'stream': 'ext://sys.stdout'
        }
    },
    'loggers': {
        'aardvark': {
            'handlers': ['file', 'console'],
            'level': 'DEBUG'
        }
    }
}"""

    with open('config.py', 'w') as filedata:
        filedata.write('# Autogenerated config file\n')
        filedata.write('SWAG_BUCKET = "{bucket}"\n'.format(bucket=bucket))
        filedata.write('ROLENAME = "{role}"\n'.format(role=role_name))
        filedata.write('SQLALCHEMY_DATABASE_URI = "{uri}"\n'.format(uri=db_uri))
        filedata.write('PHANTOMJS = "{phantom}"\n'.format(phantom=phantom))
        filedata.write('SQLALCHEMY_TRACK_MODIFICATIONS = False\n')
        filedata.write(log)


@manager.option('-a', '--accounts', dest='accounts', type=unicode, default='all')
@manager.option('-r', '--arns', dest='arns', type=unicode, default='all')
def update(accounts, arns):
    """
    Asks AWS for new Access Advisor information.
    """
    accounts = _prep_accounts(accounts)
    arns = arns.split(',')
    app = create_app()
    with app.app_context():
        for account in tqdm(accounts, desc="Updating Accounts"):
            update_account(account.metadata['account_number'], app.config.get('ROLENAME'), arns)


def _prep_accounts(account_names):
    """
    Convert CLI provided account names into list of accounts from SWAG.
    Considers account aliases as well as account names.
    Returns a set of Bunch'd accounts.
    """
    app = create_app()
    with app.app_context():
        print('getting bucket {}'.format(app.config.get('SWAG_BUCKET')))
        service = {'services': {'security_monkey': {'enabled': True}}, "ours": True}
        accounts = get_all_accounts(bucket=app.config.get('SWAG_BUCKET'), **service).get('accounts')
    if account_names == 'all':
        return [Bunch(account) for account in accounts]

    lookup = {account['name']: Bunch(account) for account in accounts}
    for account in accounts:
        for alias in account['alias']:
            lookup[alias] = Bunch(account)

    matching_accounts = list()
    account_names = account_names.split(',')
    account_names = {name.lower() for name in account_names}
    for name in account_names:
        if name not in lookup:
            print('Could not find an account named %s' % name)
            continue

        matching_accounts.append(lookup[name])

    return matching_accounts


class GunicornServer(Command):
    """
    This is the main GunicornServer server, it runs the flask app with gunicorn and
    uses any configuration options passed to it.
    You can pass all standard gunicorn flags to this command as if you were
    running gunicorn itself.
    For example:
    aardvark start_api -w 4 -b 127.0.0.0:8002
    Will start gunicorn with 4 workers bound to 127.0.0.0:8002
    """
    description = 'Run the app within Gunicorn'

    def get_options(self):
        settings = make_settings()
        options = []
        for setting, klass in settings.items():
            if klass.cli:
                if klass.action:
                    if klass.action == 'store_const':
                        options.append(Option(*klass.cli, const=klass.const, action=klass.action))
                    else:
                        options.append(Option(*klass.cli, action=klass.action))
                else:
                    options.append(Option(*klass.cli))

        return options

    def run(self, *args, **kwargs):
        from gunicorn.app.wsgiapp import WSGIApplication
        from flask import current_app

        app = WSGIApplication()

        app.app_uri = 'aardvark:create_app()'
        return app.run()


def main():
    manager.add_command("start_api", GunicornServer())
    manager.run()


if __name__ == '__main__':
    manager.add_command("start_api", GunicornServer())
    manager.run()
