package UE05_031024_RegExp1;

import java.util.Arrays;
import java.util.regex.Pattern;

public class UE05_Main {
    static Pattern iPv4 = Pattern.compile("^(?:\\d{1,3}\\.){3}\\d{1,3}$");
    static Pattern iPv6 = Pattern.compile("^[a-fA-F\\d]{4}(?::[a-fA-F\\d]{4}){7}$");
    static Pattern macAddr = Pattern.compile("^(?:[a-fA-F\\d]{2}-){5}[a-fA-F\\d]{2}$");
    static Pattern classNames = Pattern.compile("^[A-Z]\\w*(?:\\.[A-Z]\\w*)*$");
    static Pattern flightNr = Pattern.compile("^[A-Z]{2,3}\\d{2,4}$");
    static Pattern floatNrs = Pattern.compile("^[+-]?\\d+(?:\\.?\\d+)?$");
    static Pattern dates = Pattern.compile("^\\d{1,2}\\.\\d{1,2}(?:\\.(?:\\d{2}|\\d{4}))?$");
    static Pattern emails = Pattern.compile("^[\\w-]*(?:\\.?[\\w-]+)*@[A-Za-z\\d-]{3,}\\.[A-Za-z]{2,}$");
    static Pattern kfzPlattes = Pattern.compile("^[A-Z]{2}-(?=.{4,5}$)[1-9]\\d*[A-NPR-Z][A-PR-Z]*$|^[A-Z]-(?=.{5,6}$)[1-9]\\d*[A-NPR-Z][A-PR-Z]*$");

    public static void main(String[] args) {
        testRegEx();
        System.out.println("\n");
        Arrays.stream(new String[]{"192.168.1.1", "255.255.255.255", "0.0.0.0", "256.100.50.25", "192.168.1.256", "192.168.-1.1", "192.168.1", "192.168.1.a", "123.456.78.90", "192.168.01.1"}).forEach(ip -> System.out.printf("IP-Adresse: %s -> %b%n", ip, isIPv4(ip)));
        System.out.println("\n");
        Arrays.stream(new String[]{"00-1A-2B-3C-4D-5E", "00-1A-2B-3C-4D-5E", "00-1A-2B-3C-4D", "00-1A-2B-3C-4D-5E-6F", "G0-1A-2B-3C-4D-5E"}).forEach(mac -> System.out.printf("MAC-Adresse: %s -> %b%n", mac, isMacAddr(mac)));
        System.out.println("\n");
        Arrays.stream(new String[]{"3.14", "-3.14", "+3.14", "0.0", "42", "-42", "+42", "3.", ".5", "3.14.15", "abc", "1e10", "2.5e3"}).forEach(dez -> System.out.printf("Dezimalzahl: %s -> %b%n", dez, isDezimal(dez)));
        System.out.println("\n");
        Arrays.stream(new String[]{"7.11.2013", "7.11.13", "01.01.2020", "1.1.99", "31.12.2024", "31.02.2020", "32.01.2020", "7.11.201", "7.11", "7.13.2020", "abc.def.ghij"}).forEach(date -> System.out.printf("Datum: %s -> %b%n", date, isDate(date)));
        System.out.println("\n");
        Arrays.stream(new String[]{"KI-1AAA", "KI-99ZZZ", "KI-10AA", "KI-999ZZ", "KI-100A", "KI-9999Z", "W-10AAA", "W-999ZZZ", "W-100AA", "W-9999ZZ", "W-1000A", "W-99999Z"}).forEach(platte -> System.out.printf("Kennzeichen: %s -> %b%n", platte, isKFZ_Kennzeichen(platte)));
    }

    public static void testRegEx() {
        System.out.println("\n" +
                "01. IPv4: \t\t\t" + "192.168.12.0".matches(iPv4.pattern()) + "\n" +
                "02. IPv4: \t\t\t" + "255.255.255.255".matches(iPv4.pattern()) + "\n\n" +
                "01. IPv6: \t\t\t" + "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff".matches(iPv6.pattern()) + "\n" +
                "02. IPv6: \t\t\t" + "abcd:ffff:1234:e5fc:12bf:5cf2:cabd:12cf".matches(iPv6.pattern()) + "\n\n" +
                "01. MAC-Adress: \t" + "F1-CB-CF-E3-CA-45".matches(macAddr.pattern()) + "\n" +
                "02. MAC-Adress: \t" + "FF-FF-FF-FF-FF-FF".matches(macAddr.pattern()) + "\n\n" +
                "01. Class names: \t" + "Regex_Main".matches(classNames.pattern()) + "\n" +
                "02. Class names: \t" + "Map.Entry".matches(classNames.pattern()) + "\n\n" +
                "01. Flight Number: \t" + "AUS1234".matches(flightNr.pattern()) + "\n" +
                "02. Flight Number: \t" + "SAS69".matches(flightNr.pattern()) + "\n\n" +
                "01. Numbers: \t\t" + "3.1415926589".matches(floatNrs.pattern()) + "\n" +
                "02. Numbers: \t\t" + String.format("%f", Math.E).matches(floatNrs.pattern()) + "\n" +
                "03. Numbers: \t\t" + "235".matches(floatNrs.pattern()) + "\n\n" +
                "01. Dates: \t\t\t" + "25.12.1969".matches(dates.pattern()) + "\n" +
                "02. Dates: \t\t\t" + "11.12.07".matches(dates.pattern()) + "\n\n" +
                "01. Emails: \t\t" + "mail@provider.com".matches(emails.pattern()) + "\n" +
                "02. Emails: \t\t" + "sew@gmail.com".matches(emails.pattern()) + "\n\n" +
                "01. Kennzeichen: \t" + "KI-1AAA".matches(kfzPlattes.pattern()) + "\n" +
                "02. Kennzeichen: \t" + "KI-99ZZZ".matches(kfzPlattes.pattern())
        );
    }

    public static boolean isIPv4(String value) {
        if (!value.matches(iPv4.pattern())) return false;
        return Arrays.stream(value.split("\\.")).noneMatch(v -> Integer.parseInt(v) > 255);
    }

    public static boolean isMacAddr(String value) {
        return value.matches(macAddr.pattern());
    }

    public static boolean isDezimal(String value) {
        return value.matches(floatNrs.pattern());
    }

    public static boolean isKFZ_Kennzeichen(String value) {
        return value.matches(kfzPlattes.pattern());
    }

    public static boolean isDate(String value) {
        if (!value.matches(dates.pattern())) return false;
        String[] values = value.split("\\.");
        return isValidDate(Integer.parseInt(values[0]), Integer.parseInt(values[1]));
    }

    public static boolean isValidDate(int d, int m) {
        return (m <= 12 && m >= 1) && (d >= 1 && d <= lastDayInMonth(m));
    }

    public static int lastDayInMonth(int m) {
        if (m == 2) return 28;
        else if (m == 4 || m == 6 || m == 9 || m == 11) return 30;
        return 31;
    }
}