# This file is part of Pantry, command-line nutrient analysis.
# 
# Version 23, released Friday, November 09, 2007.
# 
# Copyright 2007 Omari Norman.
# 
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated
# documentation files (the "Software"), to deal in the
# Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute,
# sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
# 
# The above copyright notice and this permission notice shall
# be included in all copies or substantial portions of the
# Software.
# 
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
# OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# 
# Pantry's "built-in" XML validator is a modified version of
# xmlproc.  xmlproc is Copyright 1998-2000 by Lars Marius
# Garshol, Oslo, Norway.
# 
# All Rights Reserved
# 
# Permission to use, copy, modify, and distribute this
# software and its documentation for any purpose and without
# fee is hereby granted, provided that the above copyright
# notice appear in all copies and that modified copies are
# clearly marked as such.
# 
# LARS MARIUS GARSHOL DISCLAIMS ALL WARRANTIES WITH REGARD TO
# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL LARS MARIUS
# GARSHOL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
# DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
# USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

from __future__ import division

class Reports(object):
    """ Print out food reports. """
    
    def __init__(self, reportsWanted, prog, output, errors, sortFields, 
            sortOrders, nutList, localReportDir):
        from pantry.lib import foods
        from pantry.lib import io
        import reports
        import sys
        import os
        import errno

        reportsWanted = reportsWanted.split('-')
        self.sortOrders = sortOrders
        self.nutList = nutList
        self.prog = prog
        self.output = output
        self.errors = errors

        self.err = io.ErrorPrinter(io.puni(errors), prog, io.WARNING)
        allReporters = []
        if localReportDir:
            files = sorted(os.listdir(localReportDir))
            files = [os.path.join(localReportDir, filename)
                    for filename in files]
            for filename in files:
                execdict = {}
                execfile(filename, execdict)
                allReporters.extend(execdict['reports'])
        allReporters.extend(reports.reports)
        
        self.classesToPrint = []
        for reportNameWanted in reportsWanted:
            reportFound = False
            for reporter in allReporters:
                try:
                    reporterName = reporter.name
                except AttributeError:
                    reporterName = reporter.__name__
                if reporterName.startswith(reportNameWanted):
                    self.classesToPrint.append(reporter)
                    reportFound = True
                    break

            if not reportFound:
                self.err('report name %s does not exist' % reportNameWanted)

        self.sortList = []
        for char in sortFields:
            found = False
            for traitName in foods.TRAITNAMES[:10]:
                if traitName.startswith(char):
                    self.sortList.append((foods.TRAITSBYNAME[traitName],
                        foods.ASCENDING))
                    found = True
                    break
                elif traitName.startswith(char.lower()):
                    self.sortList.append((foods.TRAITSBYNAME[traitName],
                        foods.DESCENDING))
                    found = True
                    break
            if not found:
                self.err("sort trait %s not recognized" % char)

        self.needNuts = False
        for rptClass in self.classesToPrint:
            try:
                needNuts = rptClass.needNuts
            except AttributeError:
                needNuts = False
            if needNuts:
                self.needNuts = True
                return

    def printReports(self, cabinet):
        from pantry.lib import foods
        from pantry.lib import cabinets
        import inspect
        goalReporter = cabinets.GoalReporter(self.nutList, cabinet)

        allArgs = {
                'prog':self.prog,
                'stdout':self.output,
                'stderr':self.errors,
                'goalReporter':goalReporter,
                'cabinet':cabinet,
                }

        instancesToPrint = []
        for rptClass in self.classesToPrint:
            initArgSpec = inspect.getargspec(rptClass.__init__)[0]
            initArgList = [allArgs[argName] for argName in initArgSpec[1:]]
            rptInstance = rptClass(*initArgList)
            instancesToPrint.append(rptInstance)

        for instance in instancesToPrint:
            if hasattr(instance, 'printBegin'):
                instance.printBegin()

        # only sort foods if necessary
        foodsToPrint = cabinet.values()
        for instance in instancesToPrint:
            if hasattr(instance, 'printMain'):
                if self.sortList:
                    foodsToPrint = sorted(foodsToPrint,
                            foods.CmpFoods(self.sortList, self.sortOrders))
                break

        for food in foodsToPrint:
            for instance in instancesToPrint:
                if hasattr(instance, 'printMain'):
                    instance.printMain(food)

        for instance in instancesToPrint:
            if hasattr(instance, 'printEnd'):
                instance.printEnd()
