package ru.yandex.qe.dispenser.ws.abc;

import java.util.stream.Stream;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

import ru.yandex.qe.dispenser.domain.abc.AbcApi;
import ru.yandex.qe.dispenser.domain.abc.ObjectWithId;
import ru.yandex.qe.dispenser.ws.TvmDestination;

public abstract class CursorRequestBuilder<T extends ObjectWithId, B extends CursorRequestBuilder<T, B> & RequestBuilderFilterableById<T, B>>
        extends PageRequestBuilder<T, B> implements RequestBuilderFilterableById<T, B> {

    private final static String ID_FIELD = "id";

    @Nullable
    protected String cursor;

    @Nullable
    protected Integer smallestAcceptableServiceId;

    protected CursorRequestBuilder(final AbcApi abcApi, final TvmDestination abcTvmDestination) {
        super(abcApi, abcTvmDestination);
    }

    @Override
    public B filterById(final Integer smallestAcceptableServiceId) {
        this.smallestAcceptableServiceId = smallestAcceptableServiceId;
        return self();
    }

    @Override
    public B filterByCursor(final String cursor) {
        this.cursor = cursor;
        return self();
    }

    public B filterByCursorToId(final String cursor, final Integer smallestAcceptableServiceId) {
        if (cursor != null) {
            filterById(null);
            return filterByCursor(cursor);
        }

        filterByCursor(null);
        return filterById(smallestAcceptableServiceId);
    }

    @Nonnull
    @Override
    final protected B page(@Nullable final Integer page) {
        throw new UnsupportedOperationException("Streaming by page not supported");
    }

    @Nonnull
    @Override
    public Stream<T> stream() {
        return new AbcCursorItemIterator<>(self()).stream();
    }

    @Nullable
    @Override
    public String getFields() {
        if (fields == null) {
            fields(ID_FIELD);
        } else {
            fields.add(ID_FIELD);
        }
        return super.getFields();
    }
}
