# Copyright (c) 2004-2005 LOGILAB S.A. (Paris, FRANCE).
# http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
# Copyright (c) 2004-2005 DoCoMo Euro-Labs GmbH (Munich, Germany).
# http://www.docomolab-euro.com/ -- mailto:tarlano@docomolab-euro.com
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library 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
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
"""actions to handle activity reporting

:version: $Revision:$  
:author: Logilab

:copyright:
  2004-2005 LOGILAB S.A. (Paris, FRANCE)
  
  2004-2005 DoCoMo Euro-Labs GmbH (Munich, Germany)
  
:contact:
  http://www.logilab.fr/ -- mailto:contact@logilab.fr
  
  http://www.docomolab-euro.com/ -- mailto:tarlano@docomolab-euro.com
"""

__revision__ = '$Id: Chat.py,v  $'
__docformat__ = "restructuredtext en"

from mx.DateTime import today

from narval.public import AL_NS
from narval.interfaces.activity import IActivity
from narval.elements import create_error
from narval.elements.activity import ActivityElement
from narval.elements.email import EmailElement

# actions definitions start here ##############################################

MOD_XML = '''<?xml version="1.0" encoding="ISO-8859-1"?>
<module name="Chat" xmlns:al='%s'>''' % AL_NS

def format_reports(reports):
    """produce a string from a list of reports"""
    msgtext = []
    if reports:
        for report in reports:     
            msgtext.append('* %.2f %s' % (report.ratio, report.subject))
        title = 'activity report for %s' % (reports[0].date.strftime('%Y-%m-%d'))
        msgtext = """%s
%s

%s
""" % (title, '-'*len(title), '\n'.join(msgtext))
    else:
        msgtext = "no activity defined yet"
    return msgtext
    
def act_check_today_activity_reports(inputs):
    """check activity reports for today. If some activity reports are missing,
    ask for them, else create a full activity report
    """
    master_infos = inputs['masterinfos']
    report_config = inputs['activity-config']
    myuser = master_infos.jabberid
    assert myuser, 'no jabberid defined in master-infos element !'
    reports = [IActivity(report) for report in inputs['reports']]
    activator = inputs['activator']
    total = 0
    for report in reports:
        total += report.ratio
    if total < 1:
        if total:
            msg = activator.create_msg('you have only specified %.2f of your \
daily activity, please complete (now or later today)' % total, myuser)
        else:
            msg = activator.create_msg('what did you do today ?', myuser)
        return {'msgs': [msg]}
    else:
        sendto = report_config.sendto
        assert sendto, 'you must specify the "sendto" attribute on the activity configuration'
        msgtext = format_reports(reports)
        # FIXME: handle the sendby attribute to create either a jabber message or an email
        via = report_config.sendvia
        if via == 'im':
            msgs = [activator.create_msg(msgtext, sendto)]
            email = None
        else: # via == 'email'
            msgs = []
            email = EmailElement(to = sendto,
                                 from_name = master_infos.username,
                                 from_address = master_infos.email,
                                 subject='[activity]', type='outgoing')
            email.body = msgtext
        if via == 'email' or master_infos.email != sendto:
            info = activator.create_msg('your daily activity report has been sent to %s' % sendto,
                                        myuser)
            msgs.append(info)
        return {'msgs': msgs, 'email': email}

MOD_XML = MOD_XML + """
<al:action name='check-today-activity' func='act_check_today_activity_reports'>
  <al:description lang='en'>%s</al:description>

  <al:input id='activator'>
    <al:match>isinstance(elmt, JabberActivatorElement)</al:match>
  </al:input>
  <al:input id='masterinfos'>
    <al:match>isinstance(elmt, MasterInformationsElement)</al:match>
  </al:input>
  <al:input id='activity-config'>
    <al:match>isinstance(elmt, ActivityConfigurationElement)</al:match>
  </al:input>
  <al:input id='reports' list='yes' optional='yes'>
    <al:match>IActivity(elmt).date == today()</al:match>
  </al:input>
  
  <al:output id='msgs' optional='yes' list='yes'>
    <al:match>IIMessage(elmt).type == 'outgoing'</al:match>
  </al:output>
  <al:output id='email' optional='yes'>
    <al:match>isinstance(elmt, EmailElement) and elmt.type == 'outgoing'</al:match>
  </al:output>
</al:action>""" % act_check_today_activity_reports.__doc__


def act_activity_report_command(inputs):
    """handle a message querying for the activity on a(several)
    project(s) and print a report
    """
    cmd = inputs['command']
    msg = cmd.from_msg
    reports = [IActivity(report) for report in inputs['reports']]
    msgtext = format_reports(reports)
    # list selected activities
    return {'msgs': msg.build_reply(msgtext)}

MOD_XML = MOD_XML + """
<al:action name='activity-report-command' func='act_activity_report_command'>
  <al:description lang='en'>%s</al:description>

  <al:input id='command' use='yes'>
    <al:match>ICommand(elmt).name == 'activity_report'</al:match>
  </al:input>
  <al:input id='reports' list='yes' optional='yes'>
    <al:match>IActivity(elmt).date == today()</al:match>
  </al:input>
  
  <al:output id='msgs'>
    <al:match>IIMessage(elmt).type == 'outgoing'</al:match>
  </al:output>
</al:action>
""" % act_activity_report_command.__doc__


def act_activity_notify_command(inputs):
    """handle a message notifying of some activity on a project
    and produce an Activity element
    """
    cmd = inputs['command']
    reports = inputs['reports']
    msg = cmd.from_msg
    ratio = cmd.args[0]
    error = None
    try:
        if not isinstance(ratio, (int, float)):
            if '/' in ratio:
                nom, denom = ratio.split('/')
                ratio = float(nom) / float(denom)
            else:
                ratio = float(ratio.replace(',', '.'))
    except ValueError:
        error = create_error('unable to parse ratio %r' % ratio, 'chat', msg)
    except TypeError:
        error = create_error('unable to parse ratio %r' % ratio, 'chat', msg)
    else:
        if not (-1 <= ratio <= 1):
            error = create_error('ratio %.2f out of range (-1 <= ratio <= 1)' % ratio,
                                 'chat', msg)
    if error is not None:
        return {'error': error}
    activity = ActivityElement()
    activity.ratio = ratio
    activity.subject = cmd.args[1]
    activity.date = today()
    # activity elements are persistent
    activity.persist = True
    # add to existing activity
    for report in reports:
        if report.subject == activity.subject:
            activity.ratio += report.ratio
            report.setattr((AL_NS, 'outdated'), True)
    # return activity only if ratio != 0
    if activity.ratio > 0:
        return {'activity': activity}
    else:
        return {'error': create_error('activity deleted (ratio %.2f)'\
                                      % activity.ratio, 'chat', msg)}

MOD_XML = MOD_XML + """
<al:action name='activity-notify-command' func='act_activity_notify_command'>
  <al:description lang='en'>%s</al:description>

  <al:input id='command' use='yes'>
    <al:match>ICommand(elmt).name == 'activity_notify'</al:match>
  </al:input>
  <al:input id='reports' list='yes' optional='yes'>
    <al:match>IActivity(elmt).date == today()</al:match>
  </al:input>
  
  <al:output id='activity' optional='yes'>
    <al:match>IActivity(elmt)</al:match>
  </al:output>
</al:action>
""" % act_activity_notify_command.__doc__

def act_activity_flush_command(inputs):
    """flush the current report of activity"""
    cmd = inputs['command']
    reports = inputs['reports']
    msg = cmd.from_msg
    # delete  existing activities
    for report in reports:
        report.setattr((AL_NS, 'outdated'), True)
    return {'msgs': msg.build_reply('Activity report reset')}

MOD_XML = MOD_XML + """
<al:action name='activity-flush-command' func='act_activity_flush_command'>
  <al:description lang='en'>%s</al:description>

  <al:input id='command' use='yes'>
    <al:match>ICommand(elmt).name == 'activity_flush'</al:match>
  </al:input>
  <al:input id='reports' list='yes' optional='yes'>
    <al:match>IActivity(elmt).date == today()</al:match>
  </al:input>
  
  <al:output id='msgs'>
    <al:match>IIMessage(elmt).type == 'outgoing'</al:match>
  </al:output>  
</al:action>
""" % act_activity_flush_command.__doc__


MOD_XML +=  "</module>"
