# Copied from https://github.com/ollieglass/django-shortnaturaltime
# (unmaintained/unpackaged)
from datetime import datetime, timedelta
from datetime import timezone as dtz

from django import template

register = template.Library()


def _now():
    return datetime.utcnow().replace(tzinfo=dtz.utc)


def abs_timedelta(delta):
    """Returns an "absolute" value for a timedelta, always representing a
    time distance."""
    if delta.days < 0:
        now = _now()
        return now - (now + delta)
    return delta


def date_and_delta(value):
    """Turn a value into a date and a timedelta which represents how long ago
    it was.  If that's not possible, return (None, value)."""
    now = _now()
    if isinstance(value, datetime):
        date = value
        delta = now - value
    elif isinstance(value, timedelta):
        date = now - value
        delta = value
    else:
        try:
            value = int(value)
            delta = timedelta(seconds=value)
            date = now - delta
        except (ValueError, TypeError):
            return (None, value)
    return date, abs_timedelta(delta)


def shortnaturaldelta(value, months=True):
    """Given a timedelta or a number of seconds, return a natural
    representation of the amount of time elapsed.  This is similar to
    ``naturaltime``, but does not add tense to the result.  If ``months``
    is True, then a number of months (based on 30.5 days) will be used
    for fuzziness between years."""
    now = _now()
    date, delta = date_and_delta(value)
    if date is None:
        return value

    use_months = months

    seconds = abs(delta.seconds)
    days = abs(delta.days)
    years = days // 365
    days = days % 365
    months = int(days // 30.5)

    if not years and days < 1:
        if seconds == 0:
            return "1s"
        elif seconds == 1:
            return "1s"
        elif seconds < 60:
            return "%ds" % (seconds)
        elif 60 <= seconds < 120:
            return "1m"
        elif 120 <= seconds < 3600:
            return "%dm" % (seconds // 60)
        elif 3600 <= seconds < 3600 * 2:
            return "1h"
        elif 3600 < seconds:
            return "%dh" % (seconds // 3600)
    elif years == 0:
        if days == 1:
            return "1d"
        if not use_months:
            return "%dd" % days
        else:
            if not months:
                return "%dd" % days
            elif months == 1:
                return "1m"
            else:
                return "%dm" % months
    elif years == 1:
        if not months and not days:
            return "1y"
        elif not months:
            return "1y %dd" % days
        elif use_months:
            if months == 1:
                return "1y, 1m"
            else:
                return "1y %dm" % months
        else:
            return "1y %dd" % days
    else:
        return "%dy" % years


@register.filter
def shortnaturaltime(value, future=False, months=True):
    """Given a datetime or a number of seconds, return a natural representation
    of that time in a resolution that makes sense.  This is more or less
    compatible with Django's ``naturaltime`` filter.  ``future`` is ignored for
    datetimes, where the tense is always figured out based on the current time.
    If an integer is passed, the return value will be past tense by default,
    unless ``future`` is set to True."""
    now = _now()
    date, delta = date_and_delta(value)
    if date is None:
        return value
    # determine tense by value only if datetime/timedelta were passed
    if isinstance(value, (datetime, timedelta)):
        future = date > now

    delta = shortnaturaldelta(delta)

    if delta == "a moment":
        return "now"

    return delta
