package ru.yandex.webmaster3.storage.achievements.model;

import ru.yandex.webmaster3.storage.achievements.model.official.AchievementOfficialType;

import java.beans.ConstructorProperties;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

public class AchievementService {

    private String disabledAchivementsStr;

    private String disabledOfficialAchivementsStr;

    private Set<AchievementType> disabledAchivements = null;

    private Set<AchievementOfficialType> disabledOfficialAchievements = null;

    private final static Map<AchievementTld, Set<AchievementType>> achievementTypesByTld =
            new EnumMap<>(AchievementTld.class);


    @ConstructorProperties({"disabledAchivementsStr", "disabledOfficialAchivementsStr"})
    public AchievementService(String disabledAchivementsStr, String disabledOfficialAchivementsStr) {
        this.disabledAchivementsStr = disabledAchivementsStr;
        this.disabledOfficialAchivementsStr = disabledOfficialAchivementsStr;
    }

    public void init() {
        disabledAchivements = Pattern.compile("\\s*,\\s*")
                .splitAsStream(disabledAchivementsStr)
                .filter(s -> !s.isEmpty())
                .map(AchievementType::valueOf)
                .collect(Collectors.toSet());

        disabledOfficialAchievements = Pattern.compile("\\s*,\\s*")
                .splitAsStream(disabledOfficialAchivementsStr)
                .filter(s -> !s.isEmpty())
                .map(AchievementOfficialType::valueOf)
                .collect(Collectors.toSet());

        for (AchievementType type : AchievementType.values()) {
            if (disabledAchivements.contains(type)) {
                continue;
            }
            for (AchievementTld tld : type.getPossibleTlds()) {
                achievementTypesByTld.computeIfAbsent(tld, (k) -> EnumSet.noneOf(AchievementType.class)).add(type);
            }
        }
    }

    public boolean isDisabled(AchievementType type) {
        return disabledAchivements != null && disabledAchivements.contains(type);
    }

    public boolean isDisabled(AchievementOfficialType type) {
        return disabledOfficialAchievements != null && disabledOfficialAchievements.contains(type);
    }

    public Set<AchievementType> getAllAchievementTypes(AchievementTld tld) {
        return achievementTypesByTld.get(tld);
    }
}
