import os
import shutil

import dbt.config
import dbt.clients.system
from dbt.version import _get_adapter_plugin_names
from dbt.adapters.factory import load_plugin, get_include_paths

from dbt.logger import GLOBAL_LOGGER as logger

from dbt.include.starter_project import PACKAGE_PATH as starter_project_directory

from dbt.task.base import BaseTask

DOCS_URL = 'https://docs.getdbt.com/docs/configure-your-profile'
SLACK_URL = 'https://community.getdbt.com/'

# This file is not needed for the starter project but exists for finding the resource path
IGNORE_FILES = ["__init__.py", "__pycache__"]

ON_COMPLETE_MESSAGE = """
Your new dbt project "{project_name}" was created! If this is your first time
using dbt, you'll need to set up your profiles.yml file -- this file will tell dbt how
to connect to your database. You can find this file by running:

  {open_cmd} {profiles_path}

For more information on how to configure the profiles.yml file,
please consult the dbt documentation here:

  {docs_url}

One more thing:

Need help? Don't hesitate to reach out to us via GitHub issues or on Slack:

  {slack_url}

Happy modeling!
"""


class InitTask(BaseTask):
    def copy_starter_repo(self, project_name):
        logger.debug("Starter project path: " + starter_project_directory)
        shutil.copytree(starter_project_directory, project_name,
                        ignore=shutil.ignore_patterns(*IGNORE_FILES))

    def create_profiles_dir(self, profiles_dir):
        if not os.path.exists(profiles_dir):
            msg = "Creating dbt configuration folder at {}"
            logger.info(msg.format(profiles_dir))
            dbt.clients.system.make_directory(profiles_dir)
            return True
        return False

    def create_profiles_file(self, profiles_file, sample_adapter):
        # Line below raises an exception if the specified adapter is not found
        load_plugin(sample_adapter)
        adapter_path = get_include_paths(sample_adapter)[0]
        sample_profiles_path = adapter_path / 'sample_profiles.yml'

        if not sample_profiles_path.exists():
            logger.debug(f"No sample profile found for {sample_adapter}, skipping")
            return False

        if not os.path.exists(profiles_file):
            msg = "With sample profiles.yml for {}"
            logger.info(msg.format(sample_adapter))
            shutil.copyfile(sample_profiles_path, profiles_file)
            return True

        return False

    def get_addendum(self, project_name, profiles_path):
        open_cmd = dbt.clients.system.open_dir_cmd()

        return ON_COMPLETE_MESSAGE.format(
            open_cmd=open_cmd,
            project_name=project_name,
            profiles_path=profiles_path,
            docs_url=DOCS_URL,
            slack_url=SLACK_URL
        )

    def run(self):
        project_dir = self.args.project_name
        sample_adapter = self.args.adapter
        if not sample_adapter:
            try:
                # pick first one available, often postgres
                sample_adapter = next(_get_adapter_plugin_names())
            except StopIteration:
                logger.debug("No adapters installed, skipping")

        profiles_dir = dbt.config.PROFILES_DIR
        profiles_file = os.path.join(profiles_dir, 'profiles.yml')

        self.create_profiles_dir(profiles_dir)
        if sample_adapter:
            self.create_profiles_file(profiles_file, sample_adapter)

        if os.path.exists(project_dir):
            raise RuntimeError("directory {} already exists!".format(
                project_dir
            ))

        self.copy_starter_repo(project_dir)

        addendum = self.get_addendum(project_dir, profiles_dir)
        logger.info(addendum)
