package ru.yandex.qe.dispenser.api.v1.response;

import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.stream.Stream;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.jetbrains.annotations.NotNull;

import ru.yandex.qe.dispenser.api.util.JsonSerializerBase;

@JsonSerialize(using = DiListResponse.Serializer.class)
public class DiListResponse<T> implements Iterable<T> {
    @NotNull
    private final Collection<T> results;

    public DiListResponse(@JsonProperty("result") @NotNull final Collection<T> results) {
        this.results = Collections.unmodifiableCollection(results);
    }

    @NotNull
    @Override
    public Iterator<T> iterator() {
        return results.iterator();
    }

    @NotNull
    public Stream<T> stream() {
        return results.stream();
    }

    public int size() {
        return results.size();
    }

    @NotNull
    public Collection<T> getResults() {
        return results;
    }

    public boolean isEmpty() {
        return results.isEmpty();
    }

    @NotNull
    public T getFirst() {
        return results.stream().findFirst().orElseThrow(() -> new IllegalStateException("No elements in response!"));
    }

    @NotNull
    @Override
    public String toString() {
        return results.toString();
    }

    static class Serializer<R extends DiListResponse<?>> extends JsonSerializerBase<R> {
        @Override
        public void serialize(@NotNull final R response,
                              @NotNull final JsonGenerator jg,
                              @NotNull final SerializerProvider sp) throws IOException {
            jg.writeStartObject();
            jg.writeArrayFieldStart("result");
            for (final Object el : response) {
                jg.writeObject(el);
            }
            jg.writeEndArray();
            jg.writeEndObject();
        }
    }
}
