package ru.yandex.direct.api.v5.validation.constraints;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;

import com.google.common.collect.HashMultiset;
import com.google.common.collect.Multiset;

import ru.yandex.direct.api.v5.validation.DefectType;
import ru.yandex.direct.validation.builder.ListConstraint;

import static ru.yandex.direct.api.v5.validation.DefectTypes.duplicatedElement;
import static ru.yandex.direct.utils.FunctionalUtils.mapList;

public class UniqueItemsConstraint<I> implements ListConstraint<I, DefectType> {

    private final Function<I, ?> getter;

    public UniqueItemsConstraint(Function<I, ?> getter) {
        this.getter = t -> t != null ? getter.apply(t) : null;
    }

    public UniqueItemsConstraint() {
        this.getter = t -> t;
    }

    @Override
    public Map<Integer, DefectType> apply(List<I> list) {
        Map<Integer, DefectType> defectMap = new HashMap<>();

        List<?> items = mapList(list, getter);
        Multiset<?> itemsMultiset = HashMultiset.create(items);

        for (int i = 0; i < list.size(); i++) {
            Object item = getter.apply(list.get(i));
            if (item != null && itemsMultiset.count(item) > 1) {
                defectMap.put(i, duplicatedElement());
            }
        }

        return defectMap;
    }
}
