# encoding: utf-8
# pylint: disable=invalid-name,unused-argument,too-many-arguments
"""
Application database related tasks for Invoke.

Forked from flask-migrate
"""
import argparse
import logging
import os

from ._utils import app_context_task


log = logging.getLogger(__name__) # pylint: disable=invalid-name

try:
    from alembic import __version__ as __alembic_version__
    from alembic.config import Config as AlembicConfig
    from alembic import command
except ImportError:
    log.warning("Alembic cannot be imported, so some app.db.* tasks won't be available!")
else:

    alembic_version = tuple([int(v) for v in __alembic_version__.split('.')[0:3]])


    class Config(AlembicConfig):
        """
        Custom config that overwrites template directory.
        """
        def get_template_directory(self):
            package_dir = os.path.abspath(os.path.dirname(__file__))
            return os.path.join(package_dir, 'db_templates')


def _get_config(directory, x_arg=None, opts=None):
    """
    A helper that prepares AlembicConfig instance.
    """
    config = Config(os.path.join(directory, 'alembic.ini'))
    config.set_main_option('script_location', directory)
    if config.cmd_opts is None:
        config.cmd_opts = argparse.Namespace()
    for opt in opts or []:
        setattr(config.cmd_opts, opt, True)
    if x_arg is not None:
        if not getattr(config.cmd_opts, 'x', None):
            setattr(config.cmd_opts, 'x', [x_arg])
        else:
            config.cmd_opts.x.append(x_arg)
    return config

@app_context_task(
    help={
        'directory': "migration script directory",
        'multidb': "Multiple databases migraton",
    }
)
def init(context, directory='migrations', multidb=False):
    """Generates a new migration"""
    config = Config()
    config.set_main_option('script_location', directory)
    config.config_file_name = os.path.join(directory, 'alembic.ini')
    if multidb:
        command.init(config, directory, 'flask-multidb')
    else:
        command.init(config, directory, 'flask')


@app_context_task(
    help={
        'rev_id': "Specify a hardcoded revision id instead of generating one",
        'version_path': "Specify specific path from config for version file",
        'branch_label': "Specify a branch label to apply to the new revision",
        'splice': "Allow a non-head revision as the 'head' to splice onto",
        'head': "Specify head revision or <branchname>@head to base new revision on",
        'sql': "Don't emit SQL to database - dump to standard output instead",
        'autogenerate': "Populate revision script with andidate migration operatons, based " \
                        "on comparison of database to model",
        'directory': "migration script directory",
    }
)
def revision(context, directory='migrations', message=None, autogenerate=False, sql=False,
             head='head', splice=False, branch_label=None, version_path=None, rev_id=None):
    """Create a new revision file."""
    config = _get_config(directory)
    if alembic_version >= (0, 7, 0):
        command.revision(config, message, autogenerate=autogenerate, sql=sql,
                         head=head, splice=splice, branch_label=branch_label,
                         version_path=version_path, rev_id=rev_id)
    else:
        command.revision(config, message, autogenerate=autogenerate, sql=sql)

@app_context_task(
    help={
        'rev_id': "Specify a hardcoded revision id instead of generating one",
        'version_path': "Specify specific path from config for version file",