# Copyright 2022 The HuggingFace Team. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
Import utilities: Utilities related to imports and our lazy inits.
"""

import importlib.util
import sys
from collections import OrderedDict

# The package importlib_metadata is in a different place, depending on the python version.
if sys.version_info < (3, 8):
    import importlib_metadata
else:
    import importlib.metadata as importlib_metadata


_transformers_available = importlib.util.find_spec("transformers") is not None
try:
    _ = importlib_metadata.version("transformers")
    _transformers_metadata = importlib_metadata.metadata("transformers")
except importlib_metadata.PackageNotFoundError:
    _transformers_available = False


_accelerate_available = importlib.util.find_spec("accelerate") is not None
try:
    _ = importlib_metadata.version("accelerate")
    _accelerate_metadata = importlib_metadata.metadata("accelerate")
except importlib_metadata.PackageNotFoundError:
    _accelerate_available = False


_scipy_available = importlib.util.find_spec("scipy") is not None
try:
    _ = importlib_metadata.version("scipy")
    _scipy_metadata = importlib_metadata.metadata("scipy")
except importlib_metadata.PackageNotFoundError:
    _scipy_available = False


_pyannote_available = importlib.util.find_spec("pyannote.audio") is not None
try:
    _ = importlib_metadata.version("pyannote.audio")
    _pyannote_metadata = importlib_metadata.metadata("pyannote.audio")
except importlib_metadata.PackageNotFoundError:
    _pyannote_available = False


_torchaudio_available = importlib.util.find_spec("torchaudio") is not None
try:
    _ = importlib_metadata.version("torchaudio")
    _torchaudio_metadata = importlib_metadata.metadata("torchaudio")
except importlib_metadata.PackageNotFoundError:
    _torchaudio_available = False


def is_transformers_available():
    return _transformers_available


def is_accelerate_available():
    return _accelerate_available


def is_scipy_available():
    return _scipy_available


def is_pyannote_available():
    return _pyannote_available


def is_torchaudio_available():
    return _torchaudio_available


TRANSFORMERS_IMPORT_ERROR = """
{0} requires the transformers library but it was not found in your environment. You can install it with pip: `pip install transformers`. Please note that you may need to restart your runtime after installation.
"""


ACCELERATE_IMPORT_ERROR = """
{0} requires the accelerate library but it was not found in your environment. You can install it with pip: `pip install accelerate`. Please note that you may need to restart your runtime after installation.
"""


SCIPY_IMPORT_ERROR = """
{0} requires the scipy library but it was not found in your environment. You can install it with pip: `pip install scipy`. Please note that you may need to restart your runtime after installation.
"""


PYANNOTE_IMPORT_ERROR = """
{0} requires the pyannote.audio library but it was not found in your environment. You can install it with pip: `pip install pyannote.audio`. Please note that you may need to restart your runtime after installation.
"""


TORCHAUDIO_IMPORT_ERROR = """
{0} requires the torchaudio library but it was not found in your environment. You can install it with pip: `pip install torchaudio`. Please note that you may need to restart your runtime after installation.
"""

BACKENDS_MAPPING = OrderedDict(
    [
        ("transformers", (is_transformers_available, TRANSFORMERS_IMPORT_ERROR)),
        ("accelerate", (is_accelerate_available, ACCELERATE_IMPORT_ERROR)),
        ("scipy", (is_scipy_available, SCIPY_IMPORT_ERROR)),
        ("pyannote.audio", (is_pyannote_available, PYANNOTE_IMPORT_ERROR)),
        ("torchaudio", (is_torchaudio_available, TORCHAUDIO_IMPORT_ERROR)),
    ]
)


def requires_backends(obj, backends):
    if not isinstance(backends, (list, tuple)):
        backends = [backends]

    name = obj.__name__ if hasattr(obj, "__name__") else obj.__class__.__name__

    checks = (BACKENDS_MAPPING[backend] for backend in backends)
    failed = [msg.format(name) for available, msg in checks if not available()]
    if failed:
        raise ImportError("".join(failed))


class DummyObject(type):
    """
    Metaclass for the dummy objects. Any class inheriting from it will return the ImportError generated by
    `requires_backend` each time a user tries to access any method of that class.
    """

    def __getattribute__(cls, key):
        if key.startswith("_") and key != "_from_config":
            return super().__getattribute__(key)
        requires_backends(cls, cls._backends)
