# -*- coding: utf-8 -*-

##########################################################################
# OpenLP - Open Source Lyrics Projection                                 #
# ---------------------------------------------------------------------- #
# Copyright (c) 2008-2022 OpenLP Developers                              #
# ---------------------------------------------------------------------- #
# This program is free software: you can redistribute it and/or modify   #
# it under the terms of the GNU General Public License as published by   #
# the Free Software Foundation, either version 3 of the License, or      #
# (at your option) any later version.                                    #
#                                                                        #
# This program is distributed in the hope that it will be useful,        #
# but WITHOUT ANY WARRANTY; without even the implied warranty of         #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          #
# GNU General Public License for more details.                           #
#                                                                        #
# You should have received a copy of the GNU General Public License      #
# along with this program.  If not, see <https://www.gnu.org/licenses/>. #
##########################################################################
"""
The :mod:`openlp.core.common.applocation` module provides an utility for OpenLP receiving the data path etc.
"""
import logging
import os
import sys
from pathlib import Path

import appdirs

import openlp
from openlp.core.common import get_frozen_path
from openlp.core.common.path import create_paths, resolve
from openlp.core.common.platform import is_macosx, is_win
from openlp.core.common.registry import Registry


log = logging.getLogger(__name__)

FROZEN_APP_PATH = Path(sys.argv[0]).parent
APP_PATH = Path(openlp.__file__).parent


class AppLocation(object):
    """
    The :class:`AppLocation` class is a static class which retrieves a directory based on the directory type.
    """
    AppDir = 1
    DataDir = 2
    PluginsDir = 3
    VersionDir = 4
    CacheDir = 5
    LanguageDir = 6

    @staticmethod
    def get_directory(dir_type=AppDir):
        """
        Return the appropriate directory according to the directory type.

        :param dir_type: The directory type you want, for instance the data directory. Default *AppLocation.AppDir*
        :return: The requested path
        :rtype: Path
        """
        if dir_type == AppLocation.AppDir or dir_type == AppLocation.VersionDir:
            path = get_frozen_path(FROZEN_APP_PATH, APP_PATH)
        elif dir_type == AppLocation.PluginsDir:
            path = get_frozen_path(FROZEN_APP_PATH, APP_PATH) / 'plugins'
        elif dir_type == AppLocation.LanguageDir:
            path = get_frozen_path(FROZEN_APP_PATH, _get_os_dir_path(dir_type)) / 'i18n'
        else:
            path = _get_os_dir_path(dir_type)
        return resolve(path)

    @staticmethod
    def get_data_path():
        """
        Return the path OpenLP stores all its data under.

        :return: The data path to use.
        :rtype: Path
        """
        # Check if we have a different data location.
        if Registry().get('settings').contains('advanced/data path'):
            path = Path(Registry().get('settings').value('advanced/data path'))
        else:
            path = AppLocation.get_directory(AppLocation.DataDir)
            create_paths(path)
        return path

    @staticmethod
    def get_files(section=None, extension=''):
        """
        Get a list of files from the data files path.

        :param None | str section: Defaults to *None*. The section of code getting the files - used to load from a
        section's data subdirectory.
        :param str extension: Defaults to ''. The extension to search for. For example::
            '.png'
        :return: List of files found.
        :rtype: list[Path]
        """
        path = AppLocation.get_data_path()
        if section:
            path = path / section
        try:
            file_paths = path.glob('*' + extension)
            return [file_path.relative_to(path) for file_path in file_paths]
        except OSError:
            return []

    @staticmethod
    def get_section_data_path(section):
        """
        Return the path a particular module stores its data under.

        :param str section:
        :rtype: Path
        """
        path = AppLocation.get_data_path() / section
        create_paths(path)
        return path


def _get_os_dir_path(dir_type):
    """
    Return a path based on which OS and environment we are running in.

    :param dir_type: AppLocation Enum of the requested path type
    :return: The requested path
    :rtype: Path
    """
    # If running from source, return the language directory from the source directory
    if dir_type == AppLocation.LanguageDir:
        directory = resolve(Path(openlp.__file__, '..', '..')) / 'resources'
        if directory.exists():
            return directory
    if is_win():
        openlp_folder_path = Path(os.getenv('APPDATA'), 'openlp')
        if dir_type == AppLocation.DataDir:
            return openlp_folder_path / 'data'
        elif dir_type == AppLocation.LanguageDir:
            return Path(openlp.__file__).parent
        return openlp_folder_path

    dirs = appdirs.AppDirs('openlp', multipath=True)
    if is_macosx():
        openlp_folder_path = Path(dirs.user_data_dir)
        if dir_type == AppLocation.DataDir:
            return openlp_folder_path / 'Data'
        elif dir_type == AppLocation.LanguageDir:
            return Path(openlp.__file__).parent
        return openlp_folder_path
    else:
        if dir_type == AppLocation.LanguageDir:
            site_dirs = dirs.site_data_dir.split(os.pathsep)
            directory = Path(site_dirs[0])
            if directory.exists():
                return directory
            return Path(site_dirs[1])
        if dir_type == AppLocation.DataDir:
            return Path(dirs.user_data_dir)
        elif dir_type == AppLocation.CacheDir:
            return Path(dirs.user_cache_dir)
        if dir_type == AppLocation.DataDir:
            return Path(os.getenv('HOME'), '.openlp', 'data')
        return Path(os.getenv('HOME'), '.openlp')
