package UE03_170924_Map_Birthdays;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.LocalDate;
import java.util.*;

public class BirthdayDatamining {
    List<Birthday> birthdays;

    public BirthdayDatamining(Path datei) {
        if (datei == null) return;
        List<Birthday> tempBirthdays = new ArrayList<>();
        try {
            for (String line : Files.readAllLines(datei)) {
                while (line.length() >= 11) {
                    tempBirthdays.add(new Birthday(line.substring(0, 10)));
                    if (line.length() > 11) line = line.substring(11);
                    if (line.length() == 10) tempBirthdays.add(new Birthday(line.substring(0, 10)));
                }
            }
        } catch (IOException e) {
            return;
        }
        birthdays = new ArrayList<>(tempBirthdays);
    }

    public static String formatedDate(int date) {
        return date < 10 ? "0" + date : String.valueOf(date);
    }

    public double arithmeticMiddle() {
        double output = 0;
        for (Birthday birthday : birthdays) output += birthday.getYear();
        return output / birthdays.size();
    }

    public int mostCommonYear() {
        int mostCommonYear = 0;
        int counter = 0;
        Map<Integer, Integer> statistic = new HashMap<>();
        for (Birthday birthday : birthdays)
            statistic.put(birthday.getYear(), statistic.getOrDefault(birthday.getYear(), 0) + 1);
//        int happen = 0;
        for (Map.Entry<Integer, Integer> entry : statistic.entrySet())
            if (entry.getValue() > counter) {
                counter = entry.getValue();
                mostCommonYear = entry.getKey();
//                happen = counter;
            }
//        System.out.println(happen);
        return mostCommonYear;
    }

    public Map<Integer, Integer> birthdaysPerMonth() {
        Map<Integer, Integer> statistic = new TreeMap<>();
        for (Birthday birthday : birthdays)
            statistic.put(birthday.getMonth(), statistic.getOrDefault(birthday.getMonth(), 0) + 1);
        return statistic;
    }

    public int birthdaysOnDate(int day, int month) {
        int counter = 0;
        for (Birthday birthday : birthdays)
            if (birthday.getDay() == day && birthday.getMonth() == month) counter++;
        return counter;
    }

    public int leapYear() {
        int counter = 0;
        for (Birthday birthday : birthdays)
            if ((birthday.getYear() % 4 == 0 && birthday.getYear() % 100 != 0) || (birthday.getYear() % 400 == 0))
                counter++;
        return counter;
    }

    public Birthday youngestBirthday() {
        LocalDate latestDate = LocalDate.MIN;
        for (Birthday birthday : birthdays) {
            LocalDate currentDate;
            try {
                currentDate = LocalDate.of(birthday.getYear(), birthday.getMonth(), birthday.getDay());
            } catch (Exception e) {
                System.out.println("Fehlerhaftes Datum.");
                return new Birthday("00.00.0000");
            }
            if (currentDate.isAfter(latestDate)) latestDate = currentDate;
        }
        return new Birthday(formatedDate(latestDate.getDayOfMonth()) + '.' + formatedDate(latestDate.getMonthValue()) + '.' + latestDate.getYear());
    }

    public Birthday oldestBirthday() {
        LocalDate latestDate = LocalDate.MAX;
        for (Birthday birthday : birthdays) {
            LocalDate currentDate;
            try {
                currentDate = LocalDate.of(birthday.getYear(), birthday.getMonth(), birthday.getDay());
            } catch (Exception e) {
                System.out.println("Fehlerhaftes Datum.");
                return new Birthday("00.00.0000");
            }
            if (currentDate.isBefore(latestDate)) latestDate = currentDate;
        }
        return new Birthday(formatedDate(latestDate.getDayOfMonth()) + '.' + formatedDate(latestDate.getMonthValue()) + '.' + latestDate.getYear());
    }

    public int youngestTeacherYear() {
        Set<Integer> birthdayYear = new TreeSet<>();
        for (Birthday birthday : birthdays) birthdayYear.add(birthday.getYear());
        List<Integer> years = new ArrayList<>(birthdayYear);
        for (int i = 1; i < years.size(); i++)
            if (years.get(i - 1) + 4 <= years.get(i)) return years.get(i - 1);
        return 0;
    }

    public int howManyTeacher() {
        int output = 0;
        for (Birthday birthday : birthdays) if (birthday.getYear() <= youngestTeacherYear()) output++;
        return output;
    }

    public List<Birthday> teacherList() {
        List<Birthday> teacherList = new ArrayList<>();
        for (Birthday birthday : birthdays) if (birthday.getYear() <= youngestTeacherYear()) teacherList.add(birthday);
        return teacherList;
    }

    public List<Birthday> studentList() {
        List<Birthday> studentList = new ArrayList<>();
        for (Birthday birthday : birthdays) if (birthday.getYear() > youngestTeacherYear()) studentList.add(birthday);
        return studentList;
    }

    public int sameBirthday() {
        Map<Birthday, Integer> birthdayCounter = new TreeMap<>();
        for (Birthday birthday : birthdays) {
            Birthday date = new Birthday(formatedDate(birthday.getDay()) + "." + formatedDate(birthday.getMonth()) + ".2000");
            birthdayCounter.put(date, birthdayCounter.getOrDefault(date, 0) + 1);
        }
//        for (Map.Entry<Birthday, Integer> entry : birthdayCounter.entrySet()) if (entry.getValue() > 1) counter += entry.getValue();
//        return counter;
        return birthdayCounter.values().stream().filter(v -> v > 1).mapToInt(Integer::intValue).sum(); //Alternative (erstellt von ChatGPT) original darüber.
    }
}