# Copyright (c) 2004-2005 DoCoMo Euro-Labs GmbH (Munich, Germany).
# Copyright (c) 2001-2005 LOGILAB S.A. (Paris, FRANCE).
#
# http://www.docomolab-euro.com/ -- mailto:tarlano@docomolab-euro.com
# http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
# 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
"""narval IM presence manipulation's related actions


:version: $Revision:$  
:author: Logilab

:copyright:
  2000-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: Basic.py,v 1.70 2002/09/20 14:12:35 syt Exp $"
__docformat__ = 'restructuredtext en'

import time
import cPickle
from logilab.common.cache import Cache

from narval.public import AL_NS, expand_vars
from narval.interfaces.base import IIPresence

from narval.extensions.classify import presence_analysis

DEFAULT_PRESENCES_LOG_FILE_URL = 'file:$NARVAL_HOME/data/presences.log'

_CACHE = Cache(5)

def get_presences_info(user, create=True):
    """return recorded presence information for that user"""
    try:
        return _CACHE[user]
    except KeyError:
        filename = expand_vars('$NARVAL_HOME/data/presences_%s.log' % user)
        try:
            # fileobj = 
            data = cPickle.load(open(filename, 'rb'))
        except IOError:
            if not create:
                raise
            #fileobj = open(filename, 'wb+')
            data = []
        _CACHE[user] = filename, data
        return _CACHE[user]

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

def act_log_presence(inputs):
    """log presence information into a log file for latter analysis"""
    presence = IIPresence(inputs['presence'])
    presence_info = {'status': presence.get_status(),
                     'show': presence.get_show(),
                     'time': time.localtime(),
                     }
    # FIXME: should not access to .request
    try:
        user_id = presence.get_from_user_host()
    except KeyError:
        msg = 'trying to log a presence element without "from" field: %s' % \
              presence
        log(LOG_NOTICE, msg)
        return {}
    filename, data = get_presences_info(user_id)
    data.append(presence_info)
    # serialize and flush data
    #
    # FIXME: doing this once on __del__ would be nice but may cause
    # some concurrency problem, no ? (for instance ask for data between
    # cache deletion and __del__ call)
    stream = open(filename, 'wb')
    #fileobj.seek(0)
    cPickle.dump(data, stream)
    stream.close()
    #fileobj.truncate()
    #fileobj.flush()
    return {}

MOD_XML = MOD_XML + """
<al:action name='log-presence' func='act_log_presence'>
  <al:description lang='en'>%s</al:description>

  <al:input id='presence' use='yes'>
    <al:match>IIPresence(elmt)</al:match>
  </al:input>
</al:action>""" % act_log_presence.__doc__


def act_when_user_will_be_back(inputs):
    """try to guess when a given user will be back according to previously
    recorded presences
    """
    cmd = inputs['cmd']
    user = cmd.args[0]
    msg = cmd.from_msg
    if not '@' in user:
        user = '%s@%s' % (user, msg.get_server(conf=False))
    try:
        data = get_presences_info(user, create=False)[1]
    except IOError:
        reply = 'I don\'t have any presence information for %s' % user
    else:
        try:
            expected_ltime = presence_analysis.expected_time_back(data)
        except presence_analysis.PresenceAnalysisError, ex:
            reply = str(ex) % user
        else:
            if expected_ltime < time.localtime():
                expected_ltime = presence_analysis.extrapol_time_back(\
                    data, time.mktime(time.localtime())-time.mktime(expected_ltime))
                if expected_ltime < time.localtime():
                    reply = 'should already be there. Not enough experience to ' \
                            'get a better estimation'
                else:
                    reply = 'should already be there. New estimation ' \
                            'leads to %02dh%02d' % (
                        expected_ltime.tm_hour, expected_ltime.tm_min)
            else:
                reply = 'should be back at about %02dh%02d' % (
                    expected_ltime.tm_hour, expected_ltime.tm_min)
    return {'answer': msg.build_reply(reply)}
                                     
MOD_XML = MOD_XML + """
<al:action name='when-user-will-be-back' func='act_when_user_will_be_back'>
  <al:description lang='en'>%s</al:description>

  <al:input id='cmd' use='yes'>
    <al:match>ICommand(elmt)</al:match>
  </al:input>
  
  <al:output id='answer'>
    <al:match>IIMessage(elmt).type == 'outgoing'</al:match>
  </al:output>
</al:action>""" % act_when_user_will_be_back.__doc__

    
MOD_XML +=  "</module>"
