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

import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

import org.jetbrains.annotations.TestOnly;

import ru.yandex.qe.dispenser.domain.base_resources.BaseResourceType;

@TestOnly
public class BaseResourceTypeDaoImpl implements BaseResourceTypeDao {

    private final List<BaseResourceType> collection = new ArrayList<>();

    @Override
    public synchronized BaseResourceType create(BaseResourceType.Builder builder) {
        long nextId = collection.stream().max(Comparator.comparing(BaseResourceType::getId))
                .map(BaseResourceType::getId).orElse(-1L) + 1L;
        BaseResourceType result = builder.build(nextId);
        if (collection.stream().anyMatch(t -> t.getKey().equals(result.getKey()))) {
            throw new IllegalArgumentException("Conflicting base resource type already exists");
        }
        collection.add(result);
        return result;
    }

    @Override
    public synchronized Optional<BaseResourceType> getById(long id) {
        return collection.stream().filter(v -> v.getId() == id).findFirst();
    }

    @Override
    public synchronized Set<BaseResourceType> getByIds(Collection<? extends Long> ids) {
        if (ids.isEmpty()) {
            return Set.of();
        }
        return collection.stream().filter(v -> ids.contains(v.getId())).collect(Collectors.toSet());
    }

    @Override
    public synchronized List<BaseResourceType> getPage(Long idFrom, int size) {
        return Optional.ofNullable(idFrom).map(from -> collection.stream()
                        .sorted(Comparator.comparing(BaseResourceType::getId))
                        .filter(v -> v.getId() > from).limit(size).collect(Collectors.toList()))
                .orElseGet(() -> collection.stream().sorted(Comparator.comparing(BaseResourceType::getId))
                        .limit(size).collect(Collectors.toList()));
    }

    @Override
    public synchronized Set<BaseResourceType> getByServiceId(long serviceId) {
        return collection.stream().filter(v -> v.getServiceId() == serviceId).collect(Collectors.toSet());
    }

    @Override
    public synchronized Optional<BaseResourceType> getByIdForUpdate(long id) {
        return collection.stream().filter(v -> v.getId() == id).findFirst();
    }

    @Override
    public synchronized Set<BaseResourceType> getByServiceIdForUpdate(long serviceId) {
        return collection.stream().filter(v -> v.getServiceId() == serviceId).collect(Collectors.toSet());
    }

    @Override
    public synchronized void clear() {
        collection.clear();
    }

}
