import config
import gettext
import web
from threading import Thread, Event, current_thread
from decorators import i18n
import datetime
import subprocess
import db
from main.model import Computer

def get_gettext(lang='es', localedir=None):
    if not localedir:
        localedir = config.localedir
    try:
        gtx = gettext.translation('messages',
                                   localedir,
                                   languages=[lang])
    except Exception, e:
        print "GETTEXT error: localedir: %s" % localedir
        print "GETTEXT error: %s" % e
        print "GETTEXT error: using default gettext, translations won't work"
        gtx = gettext
    return gtx

def init_actions():
    '''
    Updates the actions_panel context variable which contains a panel showing the
    actions referred to the current url.
    '''
    import admin
    url = web.ctx.fullpath
    view_path, args = admin.app._match(admin.app.mapping, url)
    action_instances = []
    for plugin in web.ctx.plugin_manager.get_enabled_plugins():
        action_instances += plugin.get_action_instances_for_url(url)
        action_instances += plugin.get_action_instances_for_view(view_path, args)
    web.ctx.context['actions_panel'] =\
        web.ctx.normal_render.panel.panel(action_instances)

def import_module(module_path):
    '''
    Imports a module from within this directory
    '''
    return __import__(module_path, fromlist=["True"])

def reset_actions():
    '''
    Resets the actions_panel context variable which contains the result of a template
    showing a panel with the actions referred to current content.

    Only used in admin.py, added as an unload hook, so that after each page is loaded,
    the actions_panel is reset and thus next page view won't show the panel with the
    previous actions.
    '''
    web.ctx.context['actions_panel'] = None

class IPConnectivityCheck(Thread):
    '''
    This class is a thread. It checks if the given IP is online.
    The result is saved in the database
    '''

    _command = 'ping -q -c2 '

    def __init__ (self, ip):
        Thread.__init__(self)
        self.ip = ip

    def run(self):
        process = subprocess.Popen(IPConnectivityCheck._command + self.ip,
                shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        print process.wait()

        orm = db.connect()
        computers = orm.query(Computer).filter(Computer.ip == self.ip)
        # only in test mode there should be multiple computers with the same ip
        for computer in computers:
            computer.online = (process.returncode == 0)
        orm.commit()

class RepeatTimer(Thread):
    '''
    A timer that given an interval, it calls to the given function periodically.
    Example usage:

    def foo(str):
        print str
        d_something()

    if __name__ == "__main__":
        timer = RepeatTimer(5, foo, ["hey! update every 5 seconds"])
        timer.start()
    '''
    def __init__(self, interval, function, args=[], kwargs={}):
        '''
        Interval given in seconds
        '''
        Thread.__init__(self)
        self.interval = interval
        self.function = function
        self.args = args
        self.kwargs = kwargs
        self.finished = Event()

    def run(self):
        while not self.finished.is_set():
            self.finished.wait(self.interval)
            if not self.finished.is_set():
                self.function(*self.args, **self.kwargs)

    def cancel(self):
        self.finished.set()



## {{{ http://code.activestate.com/recipes/576880/ (r1)
"""::::LICENSE::::
Copyright 2009 Jai Vikram Singh Verma (jaivikram[dot]verma[at]gmail[dot]com)
Copyright 2010 Eduardo Robles Elvira <edulix AT gmail DOT com>

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
either express or implied.
See the License for the specific language governing permissions
and limitations under the License.
"""

"""Module: parsedatetime

This module caters to the need of developers who
want to put time of post in terms on
"X days, Y hrs ago", "A hours B mins ago", etc.
in their applications rather then a basic timestamp
like "2009-08-15 03:03:00". Additionally it also
provides since epoch for a given datetime.

It takes in a python datetime object as an input
and provides a fancy datetime (as I call it) and
the seconds since epoch.

::::DISCLAIMER::::
1.  This module was written for my needs of this
    kind of datetime representation and it works just fine for me.
    If you feel there are imperfections, problems,
    etc. feel free to fix and publish, or bring them to my
    notice at the above mentioned email, I shall fix it.

2.  It does not take into consideration 31 day-month and
    30 day-month, it jus uses 30 as a standard month-duration.
    For the simple reason that if the developer
    wants to represent datetime as "X months, Y days ago" then
    the relative importance of 30 or 31 is insignificant.

3.  It does not take leap years into consideration, again for the
    same reason when the representation is "X year, Y months ago"
    the relative importance of 365 or 366 is insignificant.

4. Again, in any given case it provides only two most significant
   durations of time. e.g.: "1 year, 3 months, 2 days,
   12 hours, 2 minutes ago" does not make sense, 'coz the gap is
   large (in years), so the things beyond days (in this case) do
   not make much sense, hence the output shall be
   "1 year, 3 months ago".

Use, resuse, modify, contribute-back, have Fun!!
"""

@i18n
def fancy_datetime(date_time):
    """
    converts a python datetime object to the
    format "X days, Y hours ago"

    @param date_time: Python datetime object

    @return:
        fancy datetime:: string
    """
    if not date_time:
        return _('Unknown date')
    current_datetime = datetime.datetime.now()
    delta = str(current_datetime - date_time)
    if delta.find(',') > 0:
        days, hours = delta.split(',')
        days = int(days.split()[0].strip())
        hours, minutes = hours.split(':')[0:2]
    else:
        hours, minutes = delta.split(':')[0:2]
        days = 0
    days, hours, minutes = int(days), int(hours), int(minutes)
    datelets = []
    years, months, xdays = None, None, None
    if days >= 365:
        years = int(days / 365)
        datelets.append(_n('%d year', '%d years', years) % years)
        days = days % 365
    if days >= 30 and days < 365:
        months = int(days / 30)
        datelets.append(_n('%d month', '%d months', months) % months)
        days = days % 30
    if not years and days > 0 and days < 30:
        xdays = days
        datelets.append(_n('%d day', '%d days', xdays) % xdays)
    if not (months or years) and hours != 0:
        datelets.append(_n('%d hour', '%d hours', hours) % hours)
    if not (xdays or months or years):
        if minutes == 0:
            datelets.append(_('a few seconds'))
        else:
            datelets.append(_n('%d minute', '%d minutes', minutes) % minutes)
    return _('%s ago') % ', '.join(datelets)

def set_thread_orm(orm):
    '''
    Associate the given orm to the current thread, so that anyone
    can use this orm in the current thread calling to adquire_thread_orm().
    '''
    thread = current_thread()
    setattr(thread, "sqlalchemy_orm", orm)

def adquire_thread_orm():
    '''
    Returns an orm session instance that will work in current thread. If none
    is found, it will create one and call to set_thread_orm
    '''
    thread = current_thread()
    if not hasattr(thread, "sqlalchemy_orm"):
        orm = db.connect()
        orm.commit()
        set_thread_orm(orm)
    return thread.sqlalchemy_orm
