## $Id: contract_statistics.py 12663 2015-03-05 07:28:31Z henrik $
##
## Copyright (C) 2015 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 zope.i18n import translate
from zope.catalog.interfaces import ICatalog
from zope.component import queryUtility, getUtility
from zope.interface import implementer, Interface, Attribute
from waeup.ikoba.interfaces import (
    IIkobaUtils,
    CREATED, APPROVED,
    SUBMITTED, EXPIRED,
    REJECTED, AWAITING)
from waeup.ikoba.customers.interfaces import ICustomersUtils
from waeup.ikoba.interfaces import MessageFactory as _
from waeup.ikoba.reports import IReport

class IContractStatisticsReport(IReport):

    creation_dt_string = Attribute('Human readable report creation datetime')

def get_contract_stats():
    """Get contracts

    Returns a table ordered by contract type and
    contract state (cols). The result is a 3-tuple representing
    ((<TYPES>), (<STATES>), (<NUM_OF_CUSTOMERS>)). The
    (<NUM_OF_CUSTOMERS>) is an n-tuple with each entry containing the
    number of contracts found for that type and with the respective
    state.

    Sample result:

      >>> ((u'Sample Contract 1', u'Sample Contract 2'),
      ...  ('created', 'submitted for approval', 'approved'),
      ...  ((12, 10, 1), (0, 5, 25)))

    This result means: there are 5 contracts of type 'Sample Contract 2'
    are in state 'submitted'.
    """
    site = grok.getSite()
    TYPES = getUtility(ICustomersUtils).CONTYPES_DICT
    types = TYPES.keys()
    type_names = tuple(TYPES.values()) + (u'All',)
    states = (CREATED, AWAITING, SUBMITTED, APPROVED, EXPIRED, REJECTED)
    STATES = getUtility(ICustomersUtils).TRANSLATED_CONTRACT_STATES
    state_names = tuple([STATES[state] for state in states]) + (u'Total',)
    # find all contracts
    cat = queryUtility(ICatalog, name="contracts_catalog")
    contracts = cat.searchResults(contract_id=(None, None))
    # create empty table
    table = [[0 for x in xrange(len(STATES)+1)] for y in xrange(len(TYPES)+1)]
    # fill table
    for contract in contracts:
        row = types.index(contract.class_name)
        col = states.index(contract.state)
        table[row][col] += 1
        table[-1][col] += 1
        table[row][-1] += 1
        table[-1][-1] += 1
    # turn lists into tuples
    table = tuple([tuple(row) for row in table])
    return (type_names, state_names, table)


from reportlab.lib import colors
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.lib.units import cm
from reportlab.platypus import Paragraph, Table, Spacer
from waeup.ikoba.reports import IReport, IReportGenerator
from waeup.ikoba.reports import Report
from waeup.ikoba.browser.interfaces import IPDFCreator

STYLE = getSampleStyleSheet()

def tbl_data_to_table(row_names, col_names, data):
    result = []
    new_col_names = []
    for name in col_names:
        new_col_names.append(name.replace(' ', '\n'))
    head = [''] + list(new_col_names)
    result = [head]
    for idx, row_name in enumerate(row_names):
        row = [row_name] + list(data[idx])
        result.append(row)
    return result

TABLE_STYLE = [
    ('FONT', (0,0), (-1,-1), 'Helvetica', 8),
    ('FONT', (0,0), (0,-1), 'Helvetica-Bold', 8),
    ('FONT', (0,0), (-1,0), 'Helvetica-Bold', 8),
    ('FONT', (0,-1), (-1,-1), 'Helvetica-Bold', 8),
    ('FONT', (-1,0), (-1,-1), 'Helvetica-Bold', 8),
    ('ALIGN', (1,1), (-1,-1), 'RIGHT'),
    ('INNERGRID', (0,0), (-1,-1), 0.25, colors.black),
    ('LINEBELOW', (0,-1), (-1,-1), 0.25, colors.black),
    ('LINEAFTER', (-1,0), (-1,-1), 0.25, colors.black),
    ('LINEBEFORE', (-1,0), (-1,-1), 1.0, colors.black),
    ('LINEABOVE', (0,-1), (-1,-1), 1.0, colors.black),
    #('LINEABOVE', (0,0), (-1,0), 0.25, colors.black),
    ]

@implementer(IContractStatisticsReport)
class ContractStatisticsReport(Report):

    data = None

    def __init__(self, author='System'):
        super(ContractStatisticsReport, self).__init__(
            args=[], kwargs={'author':author})
        self.author = author
        self.creation_dt_string = self.creation_dt.astimezone(
            getUtility(IIkobaUtils).tzinfo).strftime("%Y-%m-%d %H:%M:%S %Z")
        self.data = get_contract_stats()

    def create_pdf(self):
        portal_language = getUtility(IIkobaUtils).PORTAL_LANGUAGE
        creator = getUtility(IPDFCreator, name='landscape')
        table_data = tbl_data_to_table(*self.data)
        col_widths = [None,] + [1.6*cm] * len(self.data[1]) + [None,]
        pdf_data = [Paragraph('<b>%s</b>' % self.creation_dt_string,
                              STYLE["Normal"]),
                    Spacer(1, 12),]
        pdf_data += [
            Table(table_data, style=TABLE_STYLE, colWidths=col_widths)]
        doc_title = translate(_('Contracts'), 'waeup.ikoba',
            target_language=portal_language)
        footer_title = doc_title

        pdf = creator.create_pdf(
            pdf_data, None, doc_title, self.author, footer_title
            )
        return pdf

@implementer(IReportGenerator)
class ContractStatisticsReportGenerator(grok.GlobalUtility):

    title = _('Contract Statistics')
    grok.name('contract_stats')

    def generate(self, site, author=None):
        result = ContractStatisticsReport(
            author=author)
        return result

###############################################################
## Browser related stuff
##
## XXX: move to local browser module
###############################################################
from waeup.ikoba.browser.layout import IkobaPage
from waeup.ikoba.reports import get_generators
from waeup.ikoba.browser.breadcrumbs import Breadcrumb
grok.templatedir('browser_templates')
class ContractStatisticsReportGeneratorPage(IkobaPage):

    grok.context(ContractStatisticsReportGenerator)
    grok.name('index.html')
    grok.require('waeup.manageReports')

    label = _('Create contract statistics report')

    @property
    def generator_name(self):
        for name, gen in get_generators():
            if gen == self.context:
                return name
        return None

    def update(self, CREATE=None):
        self.parent_url = self.url(self.context.__parent__)
        if CREATE:
            # create a new report job for contracts
            container = self.context.__parent__
            user_id = self.request.principal.id
            kw = dict()
            self.flash(_('New report is being created in background'))
            job_id = container.start_report_job(
                self.generator_name, user_id, kw=kw)
            ob_class = self.__implemented__.__name__.replace('waeup.ikoba.','')
            grok.getSite().logger.info(
                '%s - report %s created: %s' % (
                ob_class, job_id, self.context.title))
            self.redirect(self.parent_url)
            return
        return

class ContractStatisticsReportPDFView(grok.View):

    grok.context(IContractStatisticsReport)
    grok.name('pdf')
    grok.require('waeup.Public')
    prefix = ''

    def _filename(self):
        return 'ContractStatisticsReport.pdf'

    def render(self):
        filename = self._filename().replace(
            '/', '_').replace(' ','_').replace(':', '-')
        self.response.setHeader(
            'Content-Type', 'application/pdf')
        self.response.setHeader(
            'Content-Disposition:', 'attachment; filename="%s' % filename)
        pdf_stream = self.context.create_pdf()
        ob_class = self.__implemented__.__name__.replace('waeup.ikoba.','')
        grok.getSite().logger.info('%s - report %s downloaded: %s' % (
            ob_class, self.context.__name__, filename))
        return pdf_stream

class ContractStatsBreadcrumb(Breadcrumb):
    """A breadcrumb for reports.
    """
    grok.context(ContractStatisticsReportGenerator)
    title = _(u'Contract Statistics')
    target = None