import typing
import datetime as _datetime
import dateutil.relativedelta
from .common import *

def iso8601(dt: _datetime.datetime, timespec: TimeSpec=TimeSpec.NORMAL
        ) -> str:
    dt_format = dt.strftime(ISO8601_FORMAT_DT)
    tz_format = dt.strftime(ISO8601_FORMAT_TZ)

    ms_format = ""
    if timespec == TimeSpec.MILLISECOND:
        ms_format = ".%s" % str(int(dt.microsecond/1000)).zfill(3)

    return "%s%s%s" % (dt_format, ms_format, tz_format)
def iso8601_format_now(timespec: TimeSpec=TimeSpec.NORMAL) -> str:
    return iso8601(utcnow(), timespec)

def datetime_human(dt: _datetime.datetime, timespec: TimeSpec=TimeSpec.NORMAL):
    date = _datetime.datetime.strftime(dt, DATE_HUMAN)
    time = _datetime.datetime.strftime(dt, TIME_HUMAN)
    if timespec == TimeSpec.MILLISECOND:
        time += ".%s" % str(int(dt.microsecond/1000)).zfill(3)
    return "%s %s" % (date, time)
def date_human(dt: _datetime.datetime, timespec: TimeSpec=TimeSpec.NORMAL):
    return _datetime.datetime.strftime(dt, DATE_HUMAN)

def time_unit(seconds: int) -> typing.Tuple[int, str]:
    since = None
    unit = None
    if seconds >= TIME_WEEK:
        since = seconds/TIME_WEEK
        unit = "week"
    elif seconds >= TIME_DAY:
        since = seconds/TIME_DAY
        unit = "day"
    elif seconds >= TIME_HOUR:
        since = seconds/TIME_HOUR
        unit = "hour"
    elif seconds >= TIME_MINUTE:
        since = seconds/TIME_MINUTE
        unit = "minute"
    else:
        since = seconds
        unit = "second"
    since = int(since)
    if since > 1:
        unit = "%ss" % unit # pluralise the unit
    return (since, unit)

def to_pretty_time(total_seconds: int, minimum_unit: int=UNIT_SECOND,
        max_units: int=UNIT_MINIMUM) -> str:
    if total_seconds == 0:
        return "0s"

    now = utcnow()
    later = now+_datetime.timedelta(seconds=total_seconds)
    relative = dateutil.relativedelta.relativedelta(later, now)

    out: typing.List[str] = []
    if relative.years and minimum_unit >= UNIT_YEAR and len(out) < max_units:
        out.append("%dy" % relative.years)
    if relative.months and minimum_unit >= UNIT_MONTH and len(out) < max_units:
        out.append("%dmo" % relative.months)
    if relative.weeks and minimum_unit >= UNIT_WEEK and len(out) < max_units:
        out.append("%dw" % relative.weeks)
    if relative.days and minimum_unit >= UNIT_DAY and len(out) < max_units:
        out.append("%dd" % relative.days)
    if relative.hours and minimum_unit >= UNIT_HOUR and len(out) < max_units:
        out.append("%dh" % relative.hours)
    if relative.minutes and minimum_unit >= UNIT_MINUTE and len(out) < max_units:
        out.append("%dmi" % relative.minutes)
    if relative.seconds and minimum_unit >= UNIT_SECOND and len(out) < max_units:
        out.append("%ds" % relative.seconds)

    return " ".join(out)