package ru.yandex.qe.dispenser.domain.dao;

import java.io.Serializable;
import java.util.Collection;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

import org.jetbrains.annotations.NotNull;
import org.springframework.dao.EmptyResultDataAccessException;

import ru.yandex.qe.dispenser.domain.dao.validation.Validate;

public interface GenericDao<T, PK extends Serializable> {
    @NotNull
    @Validate(exists = false)
    T create(@NotNull T newInstance);

    @NotNull
    T read(@NotNull PK id) throws EmptyResultDataAccessException;

    @NotNull
    default Map<PK, T> read(@NotNull final Collection<PK> ids) {
        return ids.stream().collect(Collectors.toMap(Function.identity(), this::read));
    }

    @Validate(exists = true)
    boolean update(@NotNull T trainsientObject);

    default boolean updateAll(@NotNull final Collection<T> objects) {
        boolean someUpdated = false;
        for (final T obj : objects) {
            someUpdated |= update(obj);
        }
        return someUpdated;
    }

    @Validate(exists = true)
    boolean delete(@NotNull T persistentObject);

    default boolean contains(@NotNull final PK id) {
        try {
            read(id);
            return true;
        } catch (EmptyResultDataAccessException ignored) {
            return false;
        }
    }

    default boolean deleteAll(@NotNull final Collection<T> objects) {
        boolean someDeleted = false;
        for (final T obj : objects) {
            someDeleted |= delete(obj);
        }
        return someDeleted;
    }

    boolean clear();
}
