package de.duehl.basics.datetime.date;

/*
 * Copyright 2017 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.ArrayList;
import java.util.List;

/**
 * Dieses Enum ist für die Wochentage von Montag bis Sonntag, enthält aber auch
 * einen unbekannten Wochentag.
 *
 * @version 1.01     2017-03-17
 * @author Christian Dühl
 */

public enum Weekday {

    UNKNOWN("Wochentag nicht gewählt", -1),

    MONDAY("Montag", 0),
    TUESDAY("Dienstag", 1),
    WEDNESDAY("Mittwoch", 2),
    THURSDAY("Donnerstag", 3),
    FRIDAY("Freitag", 4),
    SATURDAY("Samstag", 5),
    SUNDAY("Sonntag", 6);

    /** Deutsche Bezeichnung für den Wochentag. */
    private final String germanName;

    /** Code des Tages, 0=Montag, 1=Dienstag, ... 6=Sonntag. */
    private final int dayCode;

    /**
     * Konstruktor.
     *
     * @param germanName
     *            Deutsche Bezeichnung für den Wochentag.
     * @param dayCode
     *            Code des Tages, 0=Montag, 1=Dienstag, ... 6=Sonntag.
     */
    private Weekday(String germanName, int dayCode) {
        this.germanName = germanName;
        this.dayCode = dayCode;
    }

    /** Getter für die deutsche Bezeichnung für den Wochentag. */
    public String getGermanName() {
        return germanName;
    }

    /** Getter für den Code des Tages, 0=Montag, 1=Dienstag, ... 6=Sonntag. */
    public int getDayCode() {
        return dayCode;
    }

    /**
     * Gibt den Passenden Tag nach einem Sonntag mit 0 startenden Index aus.
     *
     * @param sundayDayCode
     *            Ein Sonntag mit 0 startender Index.
     * @return Passender Wochentag.
     * @throws RuntimeException Wenn der dayCode nicht im Intervall [0, 6] liegt.
     */
    public static Weekday getWeekdayByDayCodeStartingSunday(int sundayDayCode) {
        if (sundayDayCode < 0 || sundayDayCode > 6) {
            throw new IllegalArgumentException("Fehlerhafter dayCode = " + sundayDayCode);
        }
        /*
         * Das muss man hier auch testen, sonst wird aus dem ungültigen sundayDayCode 7 der gültige
         * dayCode 6!
         */

        int dayCode = calculateDayCodeFromSundayCode(sundayDayCode);

        return getWeekdayByDayCode(dayCode);
    }

    private static int calculateDayCodeFromSundayCode(int sundayDayCode) {
        int dayCode;

        if (sundayDayCode == 0) {
            dayCode = 6;
        }
        else {
            dayCode = sundayDayCode - 1;
        }
        return dayCode;
    }

    /**
     * Gibt den Passenden Tag nach einem Montag mit 0 startenden Index aus.
     *
     * @param dayCode
     *            Ein Montag mit 0 startender Index.
     * @return Passender Wochentag.
     * @throws RuntimeException Wenn der dayCode nicht im Intervall [0, 6] liegt.
     */
    public static Weekday getWeekdayByDayCode(int dayCode) {
        if (dayCode < 0 || dayCode > 6) {
            throw new IllegalArgumentException("Fehlerhafter dayCode = " + dayCode);
        }

        for (Weekday weekday : values()) {
            int code = weekday.getDayCode();
            if (code == dayCode) {
                return weekday;
            }
        }

        throw new RuntimeException("Darf nicht passieren! dayCode = " + dayCode);
    }

    /**
     * Liefert das passende Objekt über den deutschen Namen des Wochentages.
     *
     * @param germanName
     *            Deutsche Bezeichnung für den Wochentag.
     * @return Passendes Weekday-Objekt.
     */
    public static Weekday determineByGermanName(String germanName) {
        for (Weekday weekday : values()) {
            if (germanName.equals(weekday.getGermanName())) {
                return weekday;
            }
        }

        if ("Sonnabend".equals(germanName)) {
            return Weekday.SATURDAY;
        }

        return Weekday.UNKNOWN;
    }

    /** Erzeugt eine Liste mit den Wochentagen, beginnend bei Montag. */
    public static List<Weekday> createDayListStartingMonday() {
        List<Weekday> list = new ArrayList<>();

        list.add(Weekday.MONDAY);
        list.add(Weekday.TUESDAY);
        list.add(Weekday.WEDNESDAY);
        list.add(Weekday.THURSDAY);
        list.add(Weekday.FRIDAY);
        list.add(Weekday.SATURDAY);
        list.add(Weekday.SUNDAY);

        return list;
    }

    /** Erzeugt eine Liste mit den deutschen Namen der Wochentage, beginnend bei Montag. */
    public static List<String> createGermanNamesListStartingMonday() {
        List<String> list = new ArrayList<>();

        for (Weekday weekday : createDayListStartingMonday()) {
            list.add(weekday.getGermanName());
        }

        return list;
    }

}
