// Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html

import type { I18n } from "./i18n";

export const SECOND = 1.0;
export const MINUTE = 60.0 * SECOND;
export const HOUR = 60.0 * MINUTE;
export const DAY = 24.0 * HOUR;
export const MONTH = 30.0 * DAY;
export const YEAR = 12.0 * MONTH;

enum TimespanUnit {
    Seconds,
    Minutes,
    Hours,
    Days,
    Months,
    Years,
}

export function unitName(unit: TimespanUnit): string {
    switch (unit) {
        case TimespanUnit.Seconds:
            return "seconds";
        case TimespanUnit.Minutes:
            return "minutes";
        case TimespanUnit.Hours:
            return "hours";
        case TimespanUnit.Days:
            return "days";
        case TimespanUnit.Months:
            return "months";
        case TimespanUnit.Years:
            return "years";
    }
}

export function naturalUnit(secs: number): TimespanUnit {
    secs = Math.abs(secs);
    if (secs < MINUTE) {
        return TimespanUnit.Seconds;
    } else if (secs < HOUR) {
        return TimespanUnit.Minutes;
    } else if (secs < DAY) {
        return TimespanUnit.Hours;
    } else if (secs < MONTH) {
        return TimespanUnit.Days;
    } else if (secs < YEAR) {
        return TimespanUnit.Months;
    } else {
        return TimespanUnit.Years;
    }
}

export function unitAmount(unit: TimespanUnit, secs: number): number {
    switch (unit) {
        case TimespanUnit.Seconds:
            return secs;
        case TimespanUnit.Minutes:
            return secs / MINUTE;
        case TimespanUnit.Hours:
            return secs / HOUR;
        case TimespanUnit.Days:
            return secs / DAY;
        case TimespanUnit.Months:
            return secs / MONTH;
        case TimespanUnit.Years:
            return secs / YEAR;
    }
}

export function studiedToday(i18n: I18n, cards: number, secs: number): string {
    const unit = naturalUnit(secs);
    const amount = unitAmount(unit, secs);
    const name = unitName(unit);

    let secsPer = 0;
    if (cards > 0) {
        secsPer = secs / cards;
    }
    return i18n.tr(i18n.TR.STATISTICS_STUDIED_TODAY, {
        cards,
        amount,
        unit: name,
        "secs-per-card": secsPer,
    });
}

function i18nKeyForUnit(i18n: I18n, unit: TimespanUnit, short: boolean): number {
    if (short) {
        switch (unit) {
            case TimespanUnit.Seconds:
                return i18n.TR.STATISTICS_ELAPSED_TIME_SECONDS;
            case TimespanUnit.Minutes:
                return i18n.TR.STATISTICS_ELAPSED_TIME_MINUTES;
            case TimespanUnit.Hours:
                return i18n.TR.STATISTICS_ELAPSED_TIME_HOURS;
            case TimespanUnit.Days:
                return i18n.TR.STATISTICS_ELAPSED_TIME_DAYS;
            case TimespanUnit.Months:
                return i18n.TR.STATISTICS_ELAPSED_TIME_MONTHS;
            case TimespanUnit.Years:
                return i18n.TR.STATISTICS_ELAPSED_TIME_YEARS;
        }
    } else {
        switch (unit) {
            case TimespanUnit.Seconds:
                return i18n.TR.SCHEDULING_TIME_SPAN_SECONDS;
            case TimespanUnit.Minutes:
                return i18n.TR.SCHEDULING_TIME_SPAN_MINUTES;
            case TimespanUnit.Hours:
                return i18n.TR.SCHEDULING_TIME_SPAN_HOURS;
            case TimespanUnit.Days:
                return i18n.TR.SCHEDULING_TIME_SPAN_DAYS;
            case TimespanUnit.Months:
                return i18n.TR.SCHEDULING_TIME_SPAN_MONTHS;
            case TimespanUnit.Years:
                return i18n.TR.SCHEDULING_TIME_SPAN_YEARS;
        }
    }
}

/// Describe the given seconds using the largest appropriate unit.
/// If precise is true, show to two decimal places, eg
/// eg 70 seconds -> "1.17 minutes"
/// If false, seconds and days are shown without decimals.
export function timeSpan(i18n: I18n, seconds: number, short = false): string {
    const unit = naturalUnit(seconds);
    const amount = unitAmount(unit, seconds);
    const key = i18nKeyForUnit(i18n, unit, short);
    return i18n.tr(key, { amount });
}

export function dayLabel(i18n: I18n, daysStart: number, daysEnd: number): string {
    const larger = Math.max(Math.abs(daysStart), Math.abs(daysEnd));
    const smaller = Math.min(Math.abs(daysStart), Math.abs(daysEnd));
    if (larger - smaller <= 1) {
        // singular
        if (daysStart >= 0) {
            return i18n.tr(i18n.TR.STATISTICS_IN_DAYS_SINGLE, { days: daysStart });
        } else {
            return i18n.tr(i18n.TR.STATISTICS_DAYS_AGO_SINGLE, { days: -daysStart });
        }
    } else {
        // range
        if (daysStart >= 0) {
            return i18n.tr(i18n.TR.STATISTICS_IN_DAYS_RANGE, {
                daysStart,
                daysEnd: daysEnd - 1,
            });
        } else {
            return i18n.tr(i18n.TR.STATISTICS_DAYS_AGO_RANGE, {
                daysStart: Math.abs(daysEnd),
                daysEnd: -daysStart - 1,
            });
        }
    }
}
