## $Id: browser.py 13584 2016-01-11 06:09:59Z henrik $
##
## Copyright (C) 2012 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
##
import grok
from datetime import datetime, timedelta
from zope.component import getUtility
from zope.security import checkPermission
from waeup.kofa.interfaces import IKofaUtils
from waeup.kofa.utils.helpers import to_timezone
from waeup.kofa.browser.layout import UtilityView, KofaPage
from waeup.kofa.browser.viewlets import ManageActionButton
from waeup.kofa.students.interfaces import IStudentsUtils
from waeup.kofa.students.browser import OnlinePaymentDisplayFormPage as OPDPStudent
from waeup.kofa.applicants.browser import OnlinePaymentDisplayFormPage as OPDPApplicant
from kofacustom.nigeria.interswitch.helpers import (
    query_interswitch, write_payments_log)
from kofacustom.nigeria.payments.interfaces import INigeriaOnlinePayment
from kofacustom.nigeria.students.interfaces import INigeriaStudentOnlinePayment
from kofacustom.nigeria.applicants.interfaces import INigeriaApplicantOnlinePayment
from kofacustom.nigeria.interfaces import MessageFactory as _

# Buttons

class InterswitchActionButtonStudent(ManageActionButton):
    grok.order(1)
    grok.context(INigeriaOnlinePayment)
    grok.view(OPDPStudent)
    grok.require('waeup.payStudent')
    icon = 'actionicon_pay.png'
    text = _('CollegePAY')
    target = 'goto_interswitch'

    @property
    def target_url(self):
        if self.context.p_state != 'unpaid':
            return ''
        return self.view.url(self.view.context, self.target)

class InterswitchActionButtonApplicant(InterswitchActionButtonStudent):
    grok.view(OPDPApplicant)
    grok.require('waeup.payApplicant')

class InterswitchRequestWebserviceActionButtonStudent(ManageActionButton):
    grok.order(2)
    grok.context(INigeriaOnlinePayment)
    grok.view(OPDPStudent)
    grok.require('waeup.payStudent')
    icon = 'actionicon_call.png'
    text = _('Requery CollegePAY')
    target = 'request_webservice'

    @property
    def target_url(self):
        if self.context.p_state in ('paid', 'waived'):
            return ''
        return self.view.url(self.view.context, self.target)

class InterswitchRequestWebserviceActionButtonApplicant(
    InterswitchRequestWebserviceActionButtonStudent):
    grok.view(OPDPApplicant)
    grok.require('waeup.payApplicant')

class InterswitchVerifyWebserviceActionButtonStudent(ManageActionButton):
    grok.order(3)
    grok.context(INigeriaOnlinePayment)
    grok.view(OPDPStudent)
    grok.require('waeup.manageStudent')
    icon = 'actionicon_call.png'
    text = _('Verify Payment')
    target = 'verify_payment'

    @property
    def target_url(self):
        if self.context.p_state != 'paid':
            return ''
        return self.view.url(self.view.context, self.target)

class InterswitchVerifyWebserviceActionButtonApplicant(
    InterswitchVerifyWebserviceActionButtonStudent):
    grok.view(OPDPApplicant)
    grok.require('waeup.manageApplication')


# Webservice request views

class InterswitchPaymentRequestWebservicePageStudent(UtilityView, grok.View):
    """ Request webservice view for the CollegePAY gateway
    """
    grok.context(INigeriaStudentOnlinePayment)
    grok.name('request_webservice')
    grok.require('waeup.payStudent')

    product_id = None
    gateway_host = None
    gateway_url = None
    https = True
    mac = None

    def update(self):
        if self.context.p_state in ('paid', 'waived'):
            self.flash(_('This ticket has already been paid.'), type='danger')
            return
        student = self.context.student
        success, msg, log = query_interswitch(
            self.context, self.product_id,
            self.gateway_host, self.gateway_url,
            self.https, self.mac, False)
        student.writeLogMessage(self, log)
        if not success:
            self.flash(msg, type='danger')
            return
        write_payments_log(student.student_id, self.context)
        flashtype, msg, log = self.context.doAfterStudentPayment()
        if log is not None:
            student.writeLogMessage(self, log)
        self.flash(msg, type=flashtype)
        return

    def render(self):
        self.redirect(self.url(self.context, '@@index'))
        return

class InterswitchPaymentRequestWebservicePageApplicant(UtilityView, grok.View):
    """ Request webservice view for the CollegePAY gateway
    """
    grok.context(INigeriaApplicantOnlinePayment)
    grok.name('request_webservice')
    grok.require('waeup.payApplicant')

    product_id = None
    gateway_host = None
    gateway_url = None
    https = True
    mac = None

    def update(self):
        if self.context.p_state == 'paid':
            self.flash(_('This ticket has already been paid.'), type='danger')
            return
        applicant = self.context.__parent__
        success, msg, log = query_interswitch(
            self.context, self.product_id,
            self.gateway_host, self.gateway_url,
            self.https, self.mac, False)
        applicant.writeLogMessage(self, log)
        if not success:
            self.flash(msg, type='danger')
            return
        write_payments_log(applicant.applicant_id, self.context)
        flashtype, msg, log = self.context.doAfterApplicantPayment()
        if log is not None:
            applicant.writeLogMessage(self, log)
        self.flash(msg, type=flashtype)
        return

    def render(self):
        self.redirect(self.url(self.context, '@@index'))
        return

class InterswitchPaymentVerifyWebservicePageStudent(UtilityView, grok.View):
    """ Verify payment view for the CollegePAY gateway
    """
    grok.context(INigeriaStudentOnlinePayment)
    grok.name('verify_payment')
    grok.require('waeup.manageStudent')

    product_id = None
    gateway_host = None
    gateway_url = None
    https = True
    mac = None

    def update(self):
        if self.context.p_state  != 'paid':
            self.flash(_('This ticket has not been paid.'), type='danger')
            return
        student = self.context.student
        success, msg, log = query_interswitch(
            self.context, self.product_id,
            self.gateway_host, self.gateway_url,
            self.https, self.mac, True)
        student.writeLogMessage(self, log)
        if not success:
            self.flash(msg, type='danger')
            return
        self.flash(msg)
        return

    def render(self):
        self.redirect(self.url(self.context, '@@index'))
        return

class InterswitchPaymentVerifyWebservicePageApplicant(UtilityView, grok.View):
    """ Verify payment view for the CollegePAY gateway
    """
    grok.context(INigeriaApplicantOnlinePayment)
    grok.name('verify_payment')
    grok.require('waeup.manageApplication')

    product_id = None
    gateway_host = None
    gateway_url = None
    https = True
    mac = None

    def update(self):
        if self.context.p_state != 'paid':
            self.flash(_('This ticket has not been paid.'), type='danger')
            return
        applicant = self.context.__parent__
        success, msg, log = query_interswitch(
            self.context, self.product_id,
            self.gateway_host, self.gateway_url,
            self.https, self.mac, True)
        applicant.writeLogMessage(self, log)
        if not success:
            self.flash(msg, type='danger')
            return
        self.flash(msg)
        return

    def render(self):
        self.redirect(self.url(self.context, '@@index'))
        return

# Forwarding pages

class InterswitchPageStudent(KofaPage):
    """ View which sends a POST request to the Interswitch
    CollegePAY payment gateway.
    """
    grok.context(INigeriaOnlinePayment)
    grok.name('goto_interswitch')
    grok.template('student_goto_interswitch')
    grok.require('waeup.payStudent')
    label = _('Submit data to CollegePAY (Interswitch Payment Gateway)')
    submit_button = _('Submit')

    action = None
    site_name = None
    currency = None
    pay_item_id = None
    product_id = None
    xml_data = None
    hashvalue = None

    def init_update(self):
        if self.context.p_state == 'paid':
            return _("Payment ticket can't be re-sent to CollegePAY.")
        now = datetime.utcnow()
        if self.context.creation_date.tzinfo is not None:
            # That's bad. Please store timezone-naive datetimes only!
            now = self.context.creation_date.tzinfo.localize(now)
        time_delta = now - self.context.creation_date
        if time_delta.days > 7:
            return _("This payment ticket is too old. Please create a new ticket.")
        student = self.context.student
        certificate = getattr(student['studycourse'],'certificate',None)
        if certificate is None:
            return _("Study course data are incomplete.")
        kofa_utils = getUtility(IKofaUtils)
        student_utils = getUtility(IStudentsUtils)
        if student_utils.samePaymentMade(student, self.context.p_category,
            self.context.p_item, self.context.p_session):
            return _("This type of payment has already been made.")
        self.amount_auth = int(100 * self.context.amount_auth)
        xmldict = {}
        if certificate is not None:
            xmldict['department'] = certificate.__parent__.__parent__.code
            xmldict['faculty'] = certificate.__parent__.__parent__.__parent__.code
        else:
            xmldict['department'] = None
            xmldict['faculty'] = None
        self.category = self.context.category
        tz = kofa_utils.tzinfo
        self.local_date_time = to_timezone(
            self.context.creation_date, tz).strftime("%Y-%m-%d %H:%M:%S %Z")
        self.site_redirect_url = self.url(self.context, 'request_webservice')
        self.student = student
        self.xmldict = xmldict
        return

    def update(self):
        error = self.init_update()
        if error:
            self.flash(error, type='danger')
            self.redirect(self.url(self.context, '@@index'))
        return

class InterswitchPageApplicant(KofaPage):
    """ View which sends a POST request to the Interswitch
    CollegePAY payment gateway.
    """
    grok.context(INigeriaApplicantOnlinePayment)
    grok.require('waeup.payApplicant')
    grok.template('applicant_goto_interswitch')
    grok.name('goto_interswitch')
    label = _('Submit data to CollegePAY (Interswitch Payment Gateway)')
    submit_button = _('Submit')
    hashvalue = None

    action = None
    site_name = None
    currency = None
    pay_item_id = None
    product_id = None
    xml_data = None

    def init_update(self):
        if self.context.p_state != 'unpaid':
            return _("Payment ticket can't be re-sent to CollegePAY.")
        if self.context.__parent__.__parent__.expired \
            and self.context.__parent__.__parent__.strict_deadline:
            return _("Payment ticket can't be send to CollegePAY. "
                     "Application period has expired.")
        tz = getUtility(IKofaUtils).tzinfo
        time_delta = datetime.utcnow() - self.context.creation_date
        if time_delta.days > 7:
            return _("This payment ticket is too old. Please create a new ticket.")
        self.applicant = self.context.__parent__
        self.amount_auth = int(100 * self.context.amount_auth)
        self.category = self.context.category
        tz = getUtility(IKofaUtils).tzinfo
        self.local_date_time = to_timezone(
            self.context.creation_date, tz).strftime("%Y-%m-%d %H:%M:%S %Z")
        self.site_redirect_url = self.url(self.context, 'request_webservice')
        return

    def update(self):
        error = self.init_update()
        if error:
            self.flash(error, type='danger')
            self.redirect(self.url(self.context, '@@index'))
        return
