# Implementation of the @date and @datetime klammers (date.k).  Each takes
# the current date and time, offset by the :days argument (positive is
# future, negative is past), and formats it in the requested language.
#
# Language selection is two-level: the klammer's :lang argument overrides
# the document-wide Language state variable (declared in sks/kutil/kutil.k,
# default en; set it for a whole document with @@@state Language :value de).
#
# :number selects the purely numeric form instead — which is language-
# specific in order, separator, and padding: en 5/15/1955 (month first,
# unpadded), de 15.05.1955 (day first, zero-padded per DIN 5008).
#
# Languages are OWN TABLES, deliberately not locales: strftime's %B follows
# the process-wide C locale, which must be generated on the host (the
# containers ship minimal locale support) and is global mutable state in the
# embedded interpreter — the same reason @table's :decimal is implemented by
# character translation.  Adding a language is adding one LANGUAGES entry:
# twelve month names and the date pattern (day/month/year; the day carries
# no leading zero).  The time suffix ", HH:MM" is language-independent.

import datetime as dt

LANGUAGES = {
    'en': {
        'months': ['January', 'February', 'March', 'April', 'May', 'June',
                   'July', 'August', 'September', 'October', 'November',
                   'December'],
        'date': '{day} {month} {year}',            # 16 June 1910
        'number': '{m}/{day}/{year}',              # 6/16/1910
    },
    'de': {
        'months': ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni',
                   'Juli', 'August', 'September', 'Oktober', 'November',
                   'Dezember'],
        'date': '{day}. {month} {year}',           # 16. Juni 1910
        'number': '{dd}.{mm}.{year}',              # 16.06.1910 (DIN 5008)
    },
}


def offset(days):
    return dt.datetime.now() + dt.timedelta(days=days or 0)


def language(K):
    """The language table for K: :lang argument, else the Language state
    variable, else English.  Returns (table, error_text)."""
    code = getattr(K, 'lang', '') or getattr(K, 'Language', '') or 'en'
    if code not in LANGUAGES:
        return None, ('ERROR: @date/@datetime: unknown language "%s" '
                      '(available: %s)'
                      % (code, ', '.join(sorted(LANGUAGES))))
    return LANGUAGES[code], None


def format_date(t, lang, number=False):
    pattern = lang['number'] if number else lang['date']
    return pattern.format(day=t.day, m=t.month,
                          dd='%02d' % t.day, mm='%02d' % t.month,
                          month=lang['months'][t.month - 1],
                          year=t.year)


def date(K):
    lang, error = language(K)
    if error:
        return error
    return format_date(offset(K.days), lang, K.number)


def datetime(K):
    lang, error = language(K)
    if error:
        return error
    t = offset(K.days)
    return format_date(t, lang, K.number) + ', %02d:%02d' % (t.hour, t.minute)
