package de.duehl.basics.datetime;

import java.text.ParseException;
import java.text.SimpleDateFormat;

/*
 * Copyright 2024 Christian Dühl. All rights reserved.
 *
 * This program is free software. You can redistribute it and/or
 * modify it under the same terms as perl:
 *
 * general:  http://dev.perl.org/licenses/
 * GPL:      http://dev.perl.org/licenses/gpl1.html
 * artistic: http://dev.perl.org/licenses/artistic.html
 */

import java.util.Calendar;

import de.duehl.basics.datetime.date.DateHelper;
import de.duehl.basics.datetime.date.ImmutualDate;
import de.duehl.basics.datetime.time.ImmutualTime;
import de.duehl.basics.datetime.time.TimeHelper;

/**
 * Eine Hilfsklasse rund um das Datum und die Uhrzeit.
 *
 * @version 1.01     2024-04-26
 * @author Christian Dühl
 */

public class DateAndTimeHelper {

    /** Erzeugt das heutige Datum mit der aktuellen Uhrzeit im Format "TT.MM.YYYY, hh:mm:ss". */
    public static String now() {
        DateAndTime now = new DateAndTime();
        return now.toString();
    }

    /**
     * Erzeugt Datum und Uhrzeit passend zu den Millisekunden.
     *
     * @param timeMillis
     *            the new time in UTC milliseconds from the epoch.
     */
    public static DateAndTime millisToDateAndTime(long millis) {
        DateAndTime dateAndTime = new DateAndTime(millis);
        return dateAndTime;
    }

    /**
     * Erzeugt Datum und Uhrzeit passend zu den Millisekunden.
     *
     * @param timeMillis
     *            the new time in UTC milliseconds from the epoch.
     */
    public static String millisToDateAndTimeString(long millis) {
        DateAndTime dateAndTime = millisToDateAndTime(millis);
        return dateAndTime.toString();
    }

    /** Gibt die Zeit als "HH:MM" zurück, falls von heute, sonst als "HH:MM am TT.MM.JJJJ". */
    public static String timeWithoutSecondsWithoutDateIfFromToday(DateAndTime dateAndTime) {
        ImmutualDate date = dateAndTime.getDate();
        ImmutualTime time = dateAndTime.getTime();

        DateAndTime now = new DateAndTime();
        ImmutualDate nowDate = now.getDate();

        if (nowDate.equals(date)) {
            return time.toStringWithoutSeconds();
        }
        else {
            return time.toStringWithoutSeconds() + " am " + date.toString();
        }
    }

    /**
     * Gibt die verstrichene Zeit als "HH:MM - HH:MM" zurück, falls beide von heute sind, sonst als
     * "HH:MM am TT.MM.JJJJ - HH:MM am TT.MM.JJJJ".
     */
    public static String timePeriodWithoutSecondsWithoutDateIfFromToday(DateAndTime from,
            DateAndTime to) {
        ImmutualDate fromDate = from.getDate();
        ImmutualTime fromTime = from.getTime();

        ImmutualDate toDate = to.getDate();
        ImmutualTime toTime = to.getTime();

        DateAndTime now = new DateAndTime();
        ImmutualDate nowDate = now.getDate();

        if (nowDate.equals(fromDate) && nowDate.equals(toDate)) {
            return fromTime.toStringWithoutSeconds() + " - " + toTime.toStringWithoutSeconds();
        }
        else {
            return fromTime.toStringWithoutSeconds() + " am " + fromDate.toString()
                    + " - " + toTime.toStringWithoutSeconds() + " am " + toDate.toString();
        }
    }

    /** Erzeugt Datum und Uhrzeit aus einem Calendar-Objekt. */
    public static DateAndTime calendarToDateAndTime(Calendar cal) {
        ImmutualDate date = DateHelper.calendarToDate(cal);
        ImmutualTime time = TimeHelper.calendarToTime(cal);
        return new DateAndTime(date, time);
    }

    /**
     * Gibt den Zeitpunkt aus Datum und Uhrzeit als Millisekunden seit Epoch (01.01.1970) zurück.
     *
     * @param date
     *            Das Datum im Format "DD.MM.YYYY".
     * @param time
     *            Die Zeit im Format "hh:mm:ss".
     */
    public static long toEpoch(String date, String time) {
        if (!date.matches("\\d{2}\\.\\d{2}\\.\\d{4}")) {
            throw new RuntimeException("Das Datum '" + date + "' hat das falsche Format.");
        }
        if (!time.matches("\\d{2}:\\d{2}:\\d{2}")) {
            throw new RuntimeException("Die Zeit '" + time + "' hat das falsche Format.");
        }
        return reallyToEpoch(date, time);
    }

    private static long reallyToEpoch(String date, String time) {
        try {
            return tryToToEpoch(date, time);
        }
        catch (Exception exception) {
            throw new RuntimeException("Fehler beim Ermitteln von Epoch.\n"
                    + "\t" + "date = " + date + "\n"
                    + "\t" + "time = " + time + "\n",
                    exception);
        }
    }

    private static long tryToToEpoch(String date, String time) throws ParseException {
        SimpleDateFormat df = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss");
        java.util.Date parsedDate = df.parse(date + " " + time);
        long epoch = parsedDate.getTime();
        return epoch;
    }

}
