# ----------------------------------------------------------------------------
# Copyright (c) 2005-2021, PyInstaller Development Team.
#
# Distributed under the terms of the GNU General Public License (version 2
# or later) with exception for distributing the bootloader.
#
# The full license is in the file COPYING.txt, distributed with this software.
#
# SPDX-License-Identifier: (GPL-2.0-or-later WITH Bootloader-exception)
# ----------------------------------------------------------------------------
import os

from PyInstaller.utils import misc
from PyInstaller.utils.hooks import eval_script

__all__ = ['django_dottedstring_imports', 'django_find_root_dir']


def django_dottedstring_imports(django_root_dir):
    """
    Get all the necessary Django modules specified in settings.py.

    In the settings.py the modules are specified in several variables as strings.
    """
    pths = []
    # Extend PYTHONPATH with parent dir of django_root_dir.
    pths.append(misc.get_path_to_toplevel_modules(django_root_dir))
    # Extend PYTHONPATH with django_root_dir.
    # Often, Django users do not specify absolute imports in the settings module.
    pths.append(django_root_dir)

    default_settings_module = os.path.basename(django_root_dir) + '.settings'
    settings_module = os.environ.get('DJANGO_SETTINGS_MODULE', default_settings_module)
    env = {'DJANGO_SETTINGS_MODULE': settings_module, 'PYTHONPATH': os.pathsep.join(pths)}
    ret = eval_script('django_import_finder.py', env=env)

    return ret


def django_find_root_dir():
    """
    Return path to directory (top-level Python package) that contains main django files. Return None if no directory
    was detected.

    Main Django project directory contain files like '__init__.py', 'settings.py' and 'url.py'.

    In Django 1.4+ the script 'manage.py' is not in the directory with 'settings.py' but usually one level up. We
    need to detect this special case too.
    """
    # 'PyInstaller.config' cannot be imported as other top-level modules.
    from PyInstaller.config import CONF

    # Get the directory with manage.py. Manage.py is supplied to PyInstaller as the first main executable script.
    manage_py = CONF['main_script']
    manage_dir = os.path.dirname(os.path.abspath(manage_py))

    # Get the Django root directory. The directory that contains settings.py and url.py. It could be the directory
    # containing manage.py or any of its subdirectories.
    settings_dir = None
    files = set(os.listdir(manage_dir))
    if ('settings.py' in files or 'settings' in files) and 'urls.py' in files:
        settings_dir = manage_dir
    else:
        for f in files:
            if os.path.isdir(os.path.join(manage_dir, f)):
                subfiles = os.listdir(os.path.join(manage_dir, f))
                # Subdirectory contains critical files.
                if ('settings.py' in subfiles or 'settings' in subfiles) and 'urls.py' in subfiles:
                    settings_dir = os.path.join(manage_dir, f)
                    break  # Find the first directory.

    return settings_dir
