# This code is part of Qiskit.
#
# (C) Copyright IBM 2017.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.

"""This module implements the legacy abstract base class for backend modules.

To create add-on backend modules subclass the Backend class in this module.
Doing so requires that the required backend interface is implemented.
"""

from abc import ABC, abstractmethod
import warnings

from qiskit.version import VERSION as __version__
from .models import BackendStatus


class BaseBackend(ABC):
    """Legacy Base class for backends."""

    @abstractmethod
    def __init__(self, configuration, provider=None):
        """DEPRECATED Legacy base class for backends.

        This method should initialize the module and its configuration, and
        raise an exception if a component of the module is
        not available.

        Args:
            configuration (BackendConfiguration): backend configuration
            provider (BaseProvider): provider responsible for this backend

        Raises:
            QiskitError: if an error occurred when instantiating the backend.
        """
        warnings.warn(
            "The BaseBackend abstract interface is deprecated as of "
            "the 0.18.0 release and will be removed in a future "
            "release. Instead you should build your backends using "
            "the BackendV1 abstract class (which is the current "
            "latest version of the backend interface)",
            DeprecationWarning,
            stacklevel=2,
        )
        self._configuration = configuration
        self._provider = provider

    @abstractmethod
    def run(self, qobj):
        """Run a Qobj on the the backend.

        Args:
            qobj (Qobj): the Qobj to be executed.
        """
        pass

    def configuration(self):
        """Return the backend configuration.

        Returns:
            BackendConfiguration: the configuration for the backend.
        """
        return self._configuration

    def properties(self):
        """Return the backend properties.

        Returns:
            BackendProperties: the configuration for the backend. If the backend
            does not support properties, it returns ``None``.
        """
        return None

    def provider(self):
        """Return the backend Provider.

        Returns:
            BaseProvider: the Provider responsible for the backend.
        """
        return self._provider

    def status(self):
        """Return the backend status.

        Returns:
            BackendStatus: the status of the backend.
        """
        return BackendStatus(
            backend_name=self.name(),
            backend_version=__version__,
            operational=True,
            pending_jobs=0,
            status_msg="",
        )

    def name(self):
        """Return the backend name.

        Returns:
            str: the name of the backend.
        """
        return self._configuration.backend_name

    def version(self):
        """Return the backend version.

        Returns:
            str: the X.X.X version of the backend.
        """
        return self._configuration.backend_version

    def __str__(self):
        return self.name()

    def __repr__(self):
        """Official string representation of a Backend.

        Note that, by Qiskit convention, it is consciously *not* a fully valid
        Python expression. Subclasses should provide 'a string of the form
        <...some useful description...>'. [0]

        [0] https://docs.python.org/3/reference/datamodel.html#object.__repr__
        """
        return f"<{self.__class__.__name__}('{self.name()}') from {self._provider}()>"
