package ru.yandex.webmaster3.storage.util.clickhouse2.query;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import com.google.common.collect.Lists;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.tuple.Pair;
import ru.yandex.webmaster3.storage.util.clickhouse2.query.types.LimitBy;

/**
 * @author tsyplyaev
 */
public class GroupableLimitableOrderable extends Statement {
    public GroupableLimitableOrderable() {
    }

    public GroupableLimitableOrderable(Statement prev) {
        super(prev);
    }

    public GroupBy groupBy(Object field) {
        next = new GroupBy(this, field);
        return (GroupBy)next;
    }

    public GroupBy groupBy(Object... field) {
        if (field.length == 0) {
            throw new IllegalArgumentException();
        }
        if (field.length == 1) {
            next = new GroupBy(this, field[0]);
        } else {
            next = new GroupBy(this, field[0], Arrays.copyOfRange(field, 1, field.length));
        }
        return (GroupBy)next;
    }

    public GroupBy groupByWithTotals(Object field) {
        next = GroupBy.createWithTotals(groupBy(field));
        return (GroupBy)next;
    }

    public GroupBy groupByWithTotals(Object[] field) {
        next = GroupBy.createWithTotals(groupBy(field));
        return (GroupBy)next;
    }

    public Limit limit(int limit) {
        next = new Limit(limit, this);
        return (Limit)next;
    }

    public Limit limit(Integer skip, int limit) {
        next = new Limit(skip, limit, this);
        return (Limit)next;
    }

    public LimitBy limitBy(int limit, String ... fields) {
        next = new LimitBy(limit, Arrays.asList(fields), this);
        return (LimitBy) next;
    }

    public OrderBy orderBy(Object field, OrderBy.Direction direction) {
        OrderBy.Direction d = ObjectUtils.defaultIfNull(direction, OrderBy.Direction.ASC);
        next = new OrderBy(Collections.singletonList(Pair.of(field, d)), this);
        return (OrderBy)next;
    }

    public OrderBy orderBy(List<Pair<Object, OrderBy.Direction>> order) {
        next = new OrderBy(Lists.newArrayList(order), this);
        return (OrderBy)next;
    }
}
