from datetime import date, timedelta

from django import template
from django.utils import formats, timezone
from django.utils.translation import gettext as _

from ..models import COFActuPage, COFRootPage

register = template.Library()


@register.filter()
def obfuscate_mail(value):
    val = value.replace("", "-").replace("@", "arbre").replace(".", "pont")[1:]
    return val


@register.inclusion_tag("cofcms/calendar.html", takes_context=True)
def calendar(context, month=None, year=None):
    now = timezone.now()
    if month is None:
        month_start = date(now.year, now.month, 1)
    else:
        month_start = date(year, month, 1)
    next_month = month_start + timedelta(days=32)
    next_month = date(next_month.year, next_month.month, 1)
    prev_month = month_start - timedelta(days=2)
    month_prestart = month_start - timedelta(days=month_start.weekday())
    month_postend = next_month + timedelta(days=(next_month.weekday() + 6) % 7)
    events = (
        COFActuPage.objects.live()
        .filter(date_start__range=[month_prestart, month_postend], is_event=True)
        .order_by("-date_start")
    )
    events = list(events)
    weeks = []
    curday = month_prestart
    deltaday = timedelta(days=1)
    while curday < next_month and len(weeks) < 10:
        week = []
        for k in range(7):
            curevents = []
            for k in range(len(events) - 1, -1, -1):
                e = events[k]
                if e.date_start.date() > curday:
                    break
                if (e.date_start if e.date_end is None else e.date_end).date() < curday:
                    del events[k]
                else:
                    curevents.append(e)
            day = {
                "day": curday.day,
                "date": curday,
                "class": (
                    ("today " if curday == now.date() else "")
                    + (
                        "in "
                        if (
                            curday.month == month_start.month
                            and curday.year == month_start.year
                        )
                        else "out "
                    )
                    + ("hasevent" if len(curevents) > 0 else "")
                ),
                "events": curevents,
            }
            week.append(day)
            curday += deltaday
        weeks.append(week)

    # Calendar next/prev urls
    try:
        utilpage = COFRootPage.objects.live()[0]
    except COFRootPage.DoesNotExist:
        utilpage = None
    request = context["request"]
    burl = utilpage.get_url(request)
    prev_url = burl + utilpage.reverse_subpage(
        "calendar", args=[str(prev_month.year), str(prev_month.month)]
    )
    next_url = burl + utilpage.reverse_subpage(
        "calendar", args=[str(next_month.year), str(next_month.month)]
    )
    context.push(
        {
            "events": events,
            "weeks": weeks,
            "this_month": month_start,
            "prev_month": prev_url,
            "next_month": next_url,
        }
    )
    return context


@register.inclusion_tag("cofcms/mini_calendar.html")
def mini_calendar(event):
    days = []
    today = timezone.now().date()
    date_start = event.date_start.date()
    date_end = event.date_end.date() if event.date_end else date_start
    week_start = date_start - timedelta(days=date_start.weekday())
    curday = week_start
    for i in range(7):
        days.append(
            {
                "day": curday.day,
                "hasevent": curday >= date_start and curday <= date_end,
                "today": curday == today,
            }
        )
        curday += timedelta(days=1)
    return {"days": days}


@register.filter()
def dates(event):
    def factorize_suffix(a, b):
        i = -1
        imin = -min(len(a), len(b))
        while i > imin and a[i] == b[i]:
            i -= 1
        if i == -1:
            return (a, b, "")
        else:
            return (a[: i + 1], b[: i + 1], a[i + 1 :])

    datestart_string = formats.date_format(event.date_start)
    timestart_string = formats.time_format(event.date_start)
    if event.date_end:
        if event.date_end.date() == event.date_start.date():
            if event.all_day:
                return _("le {datestart}").format(datestart=datestart_string)
            else:
                return _("le {datestart} de {timestart} à {timeend}").format(
                    datestart=datestart_string,
                    timestart=timestart_string,
                    timeend=formats.time_format(event.date_end),
                )
        else:
            dateend_string = formats.date_format(event.date_end)
            diffstart, diffend, common = factorize_suffix(
                datestart_string, dateend_string
            )
            if event.all_day:
                return _("du {datestart} au {dateend}{common}").format(
                    datestart=diffstart, dateend=diffend, common=common
                )

            else:
                return _(
                    "du {datestart}{common} à {timestart} au {dateend} à {timeend}"
                ).format(
                    datestart=diffstart,
                    common=common,
                    timestart=timestart_string,
                    dateend=diffend,
                    timeend=formats.time_format(event.date_end),
                )
    else:
        if event.all_day:
            return _("le {datestart}").format(datestart=datestart_string)
        else:
            return _("le {datestart} à {timestart}").format(
                datestart=datestart_string, timestart=timestart_string
            )
