# Licensed under a 3-clause BSD style license - see LICENSE.rst

""" This module contains helper functions for accessing, downloading, and
caching data files.
"""

from __future__ import (absolute_import, division, print_function,
                        unicode_literals)

from ..extern import six
from ..extern.six.moves import urllib

import atexit
import contextlib
import fnmatch
import hashlib
import os
import io
import shutil
import socket
import sys
import time

from tempfile import NamedTemporaryFile, gettempdir
from warnings import warn

from .. import config as _config
from ..utils.exceptions import AstropyWarning


__all__ = [
    'Conf', 'conf', 'get_readable_fileobj', 'get_file_contents',
    'get_pkg_data_fileobj', 'get_pkg_data_filename',
    'get_pkg_data_contents', 'get_pkg_data_fileobjs',
    'get_pkg_data_filenames', 'compute_hash', 'clear_download_cache',
    'CacheMissingWarning', 'get_free_space_in_dir',
    'check_free_space_in_dir', 'download_file',
    'download_files_in_parallel']


class Conf(_config.ConfigNamespace):
    """
    Configuration parameters for `astropy.utils.data`.
    """

    dataurl = _config.ConfigItem(
        'http://data.astropy.org/',
        'URL for astropy remote data site.')
    remote_timeout = _config.ConfigItem(
        3.,
        'Time to wait for remote data queries (in seconds).',
        aliases=['astropy.coordinates.name_resolve.name_resolve_timeout'])
    compute_hash_block_size = _config.ConfigItem(
        2 ** 16,  # 64K
        'Block size for computing MD5 file hashes.')
    download_block_size = _config.ConfigItem(
        2 ** 16,  # 64K
        'Number of bytes of remote data to download per step.')
    download_cache_lock_attempts = _config.ConfigItem(
        5,
        'Number of times to try to get the lock ' +
        'while accessing the data cache before giving up.')
    delete_temporary_downloads_at_exit = _config.ConfigItem(
        True,
        'If True, temporary download files created when the cache is '
        'inaccessible will be deleted at the end of the python session.')
conf = Conf()


DATAURL = _config.ConfigAlias(
    '0.4', 'DATAURL', 'dataurl')
REMOTE_TIMEOUT = _config.ConfigAlias(
    '0.4', 'REMOTE_TIMEOUT', 'remote_timeout')
COMPUTE_HASH_BLOCK_SIZE = _config.ConfigAlias(
    '0.4', 'COMPUTE_HASH_BLOCK_SIZE', 'compute_hash_block_size')
DOWNLOAD_CACHE_BLOCK_SIZE = _config.ConfigAlias(
    '0.4', 'DOWNLOAD_CACHE_BLOCK_SIZE', 'download_block_size')
DOWNLOAD_CACHE_LOCK_ATTEMPTS = _config.ConfigAlias(
    '0.4', 'DOWNLOAD_CACHE_LOCK_ATTEMPTS', 'download_cache_lock_attempts')
DELETE_TEMPORARY_DOWNLOADS_AT_EXIT = _config.ConfigAlias(
    '0.4', 'DELETE_TEMPORARY_DOWNLOADS_AT_EXIT', 'delete_temporary_downloads_at_exit')


class CacheMissingWarning(AstropyWarning):
    """
    This warning indicates the standard cache directory is not accessible, with
    the first argument providing the warning message. If args[1] is present, it
    is a filename indicating the path to a temporary file that was created to
    store a remote data download in the absence of the cache.