from django.core.exceptions import ImproperlyConfigured
from abo.utils import get_backend_settings


class PaymentProcessorBase(object):
    """
    Base for all payment processors. It should at least be able to:
     * manage all necessary logic to accept payment from gateway, e.g. expose
       a View for incoming transaction notification status changes
    """

    #Each backend need to define this values
    BACKEND = None
    """
    This constant should be set to fully qualified python path to the module. This is also
    a name that will be used to identify and enabling this backend in django-abo
    """
    BACKEND_NAME = None
    """
    This constant should be set to human readable backend name. Consider using lazy translation strings
    for i18n support
    """
    BACKEND_ACCEPTED_CURRENCY = tuple()
    """
    This constant should be any type of iterable that defines accepted currencies by the backend. Currencies should be
    set as three letters ISO code strings (eg. 'USD', 'EUR')
    """

    @classmethod
    def get_gateway_url(cls, request):
        """
        Should return a tuple with the first item being the URL that redirects to payment Gateway
        Second item should be if the request is made via GET or POST. Third item are the parameters
        to be passed in case of a POST REQUEST. Request context need to be given because various
        payment engines requires information about client (e.g. a client IP).
        """
        raise NotImplementedError('Must be implemented in PaymentProcessor')

    @classmethod
    def get_form(cls, post_data):
        """
        Only used if the payment processor requires POST requests.
        Generates a form only containg hidden input fields.
        """
        from abo.forms import PaymentHiddenInputsPostForm
        return PaymentHiddenInputsPostForm(items=post_data)

    @classmethod
    def get_backend_setting(cls, name, default=None):
        """
        Reads ``name`` setting from backend settings dictionary.

        If `default` value is omitted, raises ``ImproperlyConfigured`` when
        setting ``name`` is not available.
        """
        backend_settings = get_backend_settings(cls.BACKEND)
        if default is not None:
            return backend_settings.get(name, default)
        else:
            try:
                return backend_settings[name]
            except KeyError:
                raise ImproperlyConfigured("subscription '%s' requires backend '%s' setting" % (cls.BACKEND, name))
