## $Id: payment.py 12141 2014-12-04 04:04:58Z uli $
##
## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
## 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 2 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, write to the Free Software
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
##
"""
These are the payment tickets.
"""
import decimal
import grok
import uuid
from datetime import datetime
from zope.event import notify
from zope.component import getUtility
from zope.i18n import translate
from waeup.ikoba.interfaces import IIkobaUtils
from waeup.ikoba.interfaces import MessageFactory as _
from waeup.ikoba.payments.interfaces import (
    IPayment, IOnlinePayment, STATE_UNPAID, STATE_FAILED, STATE_PAID,
    )
from waeup.ikoba.utils.helpers import attrs_to_fields, get_current_principal
from waeup.ikoba.utils.logger import Logger


class Payment(grok.Container, Logger):
    """This is a payment.
    """
    grok.implements(IPayment)
    grok.provides(IPayment)
    grok.baseclass()

    logger_name = 'waeup.ikoba.${sitename}.payments'
    logger_filename = 'payments.log'
    logger_format_str = '"%(asctime)s","%(user)s",%(message)s'

    def __init__(self):
        super(Payment, self).__init__()
        self.creation_date = datetime.utcnow()
        self.payment_date = None
        self.payment_id = u'PAY_' + unicode(uuid.uuid4().hex)
        self.amount = decimal.Decimal("0.00")
        self.payed_item_id = None
        self.payer_id = None
        self.state = STATE_UNPAID
        return

    def approve(self, payment_date=None):
        """A payment was approved.

        Successful ending; the payment is marked as payed.

        If `payment_date` is given, it must be a datetime object
        giving a datetime in UTC timezone.

        Raises ObjectModifiedEvent.
        """
        if payment_date is None:
            payment_date = datetime.utcnow()
        self.payment_date = payment_date
        self.payment_state = STATE_PAID
        notify(grok.ObjectModifiedEvent(self))

    def mark_failed(self, reason=None):
        """Mark payment as failed.

        Raises ObjectModifiedEvent.
        """
        self.payment_state = STATE_FAILED
        notify(grok.ObjectModifiedEvent(self))


class OnlinePayment(Payment):
    """This is an online payment.
    """
    grok.implements(IOnlinePayment)
    grok.provides(IOnlinePayment)

    def approve(self):
        "Approve online payment and set to paid."
        self.r_amount_approved = self.amount_auth
        self.r_code = u'AP'
        self.p_state = 'paid'
        user = get_current_principal()
        if user is None:
            # in tests
            usertitle = 'system'
        else:
            usertitle = getattr(user, 'public_name', None)
            if not usertitle:
                usertitle = user.title
        r_desc = _('Payment approved by ${a}', mapping={'a': usertitle})
        portal_language = getUtility(IIkobaUtils).PORTAL_LANGUAGE
        self.r_desc = translate(r_desc, 'waeup.ikoba',
            target_language=portal_language)
        self.payment_date = datetime.utcnow()
        # Update catalog
        notify(grok.ObjectModifiedEvent(self))
        return

OnlinePayment = attrs_to_fields(OnlinePayment, omit=['display_item'])
