# -*- coding: utf-8 -*-
"""
    MoinMoin - AlertDate Macro

    This very complicated macro takes in a date
    and produces a label automatically based on
    how soon that date will occur.

    Depending  on when  it is,  by  default the
    following labels are used:
        Next Week (or Weekend)
        This Week (or Weekend)
        Tomorrow! or,
        Today!

    Also, a  label for  things further than two
    weeks into the future,  or past  events can
    be  configured.  Images could just  as well
    be inserted.

    Configure  the labels in wikiconfig.py  by
    adding:
         alert_date_format = ""    # format str
         alert_labels = {}         # dict defining
                                   # the following
                                   # labels:
           "today", "tomorrow",
           "thisweek", "thisweekend",
           "nextweek", "nextweekend",
           "future", "passed"

    default usage is <<AlertDate(mm/dd/yyyy)>>

    @copyright: 2004 by Arel Cordero <arel@cs.berkeley.edu>
    @license: GNU GPL, see COPYING for details.

    changes:
        12.2007 - conversion to new syntax by Bolesław Kulbabiński
"""

import time
from MoinMoin import config, wikiutil

Dependencies = []

# default variables. These can be overwritten in wikiconfig.py
class glob:
    alert_date_fmt = "%m/%d/%Y" # see time module for expl.
    alert_labels = {
          "nextweek": '(Next Week)',
          "nextweekend":'(Next Weekend)',
          "thisweek": '(This Week)',
          "thisweekend":'(This Weekend)',
          "tomorrow": '(Tomorrow!)',
          "today": '(<b>Today!</b>)',
          "passed": '',
          "future": ''}


# converts time tuple t into:
# d - number of days since epoch.
# wd - day of the week (with monday being 0)
def indays(t):
    a = list(t)
    a[3:6] = [0, 0, 0]
    d = int(time.mktime(a) / 86400.0) # divide by sec./day
    wd = t[6]                         # day of week, 0 = monday
    return (d, wd)


# Expects a single string in args that contains due date
# formatted to configured format. Default is mm/dd/yyyy
def macro_AlertDate(macro, args):

    # Check and import config variables
    if hasattr(config, "alert_date_config"):
        glob.alert_date_config = config.alert_date_config
    if hasattr(config, "alert_labels"):
        glob.alert_labels = config.alert_labels

    # Attempt to parse time according to format
    try:
       (due, d_dow) = indays(time.strptime(args, glob.alert_date_fmt))
       (local, l_dow) = indays(time.localtime())
       delta = due - local
       monday = due - d_dow

       if delta < 0:
           return glob.alert_labels.get("passed", "")
       elif delta == 0:
           return glob.alert_labels.get("today", "")
       elif delta == 1:
           return glob.alert_labels.get("tomorrow", "")
       elif local >= monday:
          if d_dow in [5, 6]:
              return glob.alert_labels.get("thisweekend", "")
          else:
              return glob.alert_labels.get("thisweek", "")
       elif local >= monday - 7:
          if d_dow in [5, 6]:
              return glob.alert_labels.get("nextweekend", "")
          else:
              return glob.alert_labels.get("nextweek", "")
       else:
           return glob.alert_labels.get("future", "")

    except (ValueError, TypeError): # Format was not understood.
       f = macro.request.formatter
       if args:
           return f.text("<<AlertDate: The date <%s> could not be parsed. It should look like: AlertDate(%s)>>" %
                     (args, time.strftime(glob.alert_date_fmt)))
       else:
           return (f.text("<<AlertDate: Usage: AlertDate(some_future_date)") +
                  f.linebreak(0) +
                  f.text("Where some_future_date takes the format: (%s)." % glob.alert_date_fmt) +
                  f.linebreak(0) +
                  f.text("For example, AlertDate(%s) >>" % time.strftime(glob.alert_date_fmt)))


def execute(macro, args):
    try:
        return wikiutil.invoke_extension_function(
                   macro.request, macro_AlertDate,
                   args, [macro])
    except ValueError, err:
        return macro.request.formatter.text(
                   "<<AlertDate: %s>>" % err.args[0])

