package ru.yandex.webmaster3.storage.util.ydb.querybuilder;

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

import org.apache.commons.lang3.tuple.Pair;

import ru.yandex.webmaster3.storage.util.ydb.query.Clause;
import ru.yandex.webmaster3.storage.util.ydb.querybuilder.typesafe.Field;
import ru.yandex.webmaster3.storage.util.ydb.querybuilder.typesafe.FieldMapper;

/**
 * ishalaru
 * 16.06.2020
 **/
abstract class SelectBaseOperation<T> {
    protected Select<T> parent;

    SelectBaseOperation(Select<T> parent) {
        this.parent = parent;
    }

    public Select.Where<T> where(Clause dbFieldCondition) {
        return parent.where(dbFieldCondition);
    }

    public Select.GroupBy<T> groupBy(Field... fields) {
        return parent.groupBy(fields);
    }

    public Select<T> order(Ordering ordering) {
        return parent.order(ordering);
    }

    public Select<T> limit(int limit) {
        parent.limit(limit);
        return parent;
    }

    public Select<T> limit(int skip, int limit) {
        parent.limit(skip, limit);
        return parent;
    }

    public Select.Having<T> having(Clause dbFieldCondition) {
        return parent.having(dbFieldCondition);
    }

    public Select.Cont<T> cont(Clause dbFieldCondition) {
        return parent.cont(dbFieldCondition);
    }

    public Select<T> getStatement() {
        return parent;
    }

    // вытаскивает до 1000 записей
    public List<T> queryForList() {
        return parent.queryForList();
    }

    public List<T> queryForList(Function<List<T>, Select<T>> continuationSupplier) {
        return parent.queryForList(continuationSupplier);
    }

    // !!! нельзя вставлять order !!!
    // сортируем по ключу key
    public <KEY> List<T> queryForList(Pair<Field<KEY>, Function<T, KEY>> key) {
        return parent.queryForList(key);
    }

    // !!! нельзя вставлять order !!!
    // сортируем по ключу key1, key2
    public <KEY1, KEY2> List<T> queryForList(Pair<Field<KEY1>, Function<T, KEY1>> key1, Pair<Field<KEY2>, Function<T, KEY2>> key2) {
        return parent.queryForList(key1, key2);
    }

    @SafeVarargs
    public final List<T> queryForList(FieldMapper<T, ? extends Object>... mappers) {
        return (List<T>) parent.queryForList(mappers);
    }

    // !!! нельзя вставлять order !!!
    // сортируем по ключу key1, key2
    public <KEY1, KEY2, KEY3> List<T> queryForList(Pair<Field<KEY1>, Function<T, KEY1>> key1,
                                                   Pair<Field<KEY2>, Function<T, KEY2>> key2,
                                                   Pair<Field<KEY3>, Function<T, KEY3>> key3) {
        return parent.queryForList(key1, key2, key3);
    }

    public T queryOne() {
        return parent.queryOne();
    }

}
