// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package io.v.baku.toolkit.bind;

import com.google.common.collect.Ordering;

import java.util.Comparator;

import io.v.rx.syncbase.RangeWatchBatch;
import io.v.rx.syncbase.RxTable;
import io.v.v23.syncbase.nosql.PrefixRange;
import io.v.v23.syncbase.nosql.RowRange;
import rx.Observable;
import rx.functions.Func1;

/**
 * Builder class for data bindings to collections derived from rows with names matching a key
 * prefix, optionally with additional filter criteria. Ordering is data driven. This type of
 * collection binding is advantageous in its simplicity, at the cost of being less flexible than
 * other collection bindings. Internally, the ordering always includes a secondary ordering on key
 * to remove ambiguity.
 * <p>
 * If {@code T} is {@link Comparable}, the default row ordering is natural ordering on row values.
 * Otherwise, the default is natural ordering on row names.
 *
 * @see BindingBuilder#forPrefix(String)
 * @see BindingBuilder#forPrefix(PrefixRange)
 */
public class PrefixBindingBuilder<T, A extends RangeAdapter>
        extends CollectionBindingBuilder<PrefixBindingBuilder<T, A>, RxTable.Row<T>, A> {
    private Class<T> mType;
    private PrefixRange mPrefix;
    private Comparator<? super RxTable.Row<T>> mOrdering;
    private Func1<String, Boolean> mKeyFilter;

    public PrefixBindingBuilder(final BindingBuilder base) {
        super(base);
    }

    public PrefixBindingBuilder<T, A> prefix(final PrefixRange prefix) {
        mPrefix = prefix;
        return this;
    }

    public PrefixBindingBuilder<T, A> prefix(final String prefix) {
        return prefix(RowRange.prefix(prefix));
    }

    /**
     * The element type for the collection, i.e. the value type for rows matching the prefix and key
     * filter.
     * <p>
     * This setter is minimally typesafe; after setting the {@code type}, clients should
     * probably also update {@code ordering} and {@code viewAdapter}.
     */
    public <U> PrefixBindingBuilder<U, A> type(final Class<U> type) {
        @SuppressWarnings("unchecked")
        final PrefixBindingBuilder<U, A> casted = (PrefixBindingBuilder<U, A>) this;
        casted.mType = type;
        return casted;
    }

    public PrefixBindingBuilder<T, A> ordering(
            final Ordering<? super RxTable.Row<? extends T>> ordering) {
        mOrdering = ordering;
        return this;
    }

    public PrefixBindingBuilder<T, A> valueOrdering(final Ordering<? super T> ordering) {
        return ordering(ordering.onResultOf(RxTable.Row::getValue));
    }

    public PrefixBindingBuilder<T, A> valueAdapter(final ViewAdapter<? super T, ?> viewAdapter) {
        return viewAdapter(new TransformingViewAdapter<>(viewAdapter, RxTable.Row::getValue));
    }

    @Override
    protected ViewAdapter<RxTable.Row<T>, ?> getDefaultViewAdapter() {
        return new TextViewAdapter(mBase.getDefaultViewAdapterContext()).map(RxTable.Row::getValue);
    }

    private Class<T> getType() {
        if (mType == null) {
            throw new IllegalStateException("Missing required type property");
        }
        return mType;
    }

    /**
     * For comparable {@code T}, default to natural ordering on values. Otherwise, default to
     * natural ordering on row names.
     */
    private Ordering<? super RxTable.Row<? extends T>> getDefaultOrdering() {
        if (mOrdering == null && Comparable.class.isAssignableFrom(getType())) {
            return Ordering.natural().onResultOf(r -> (Comparable) r.getValue());
        } else {
            return Ordering.natural().onResultOf(RxTable.Row::getRowName);
        }
    }

    public PrefixBindingBuilder<T, A> keyFilter(final Func1<String, Boolean> keyFilter) {
        mKeyFilter = keyFilter;
        return this;
    }

    public Observable<RangeWatchBatch<T>> buildPrefixWatch() {
        return mBase.mRxTable.watch(mPrefix == null? RowRange.prefix("") : mPrefix,
                mKeyFilter, getType());
    }

    private Comparator<? super RxTable.Row<T>> getOrdering() {
        return mOrdering == null ? getDefaultOrdering() : mOrdering;
    }

    @Override
    public Observable<? extends PrefixListAccumulator<T>> buildListAccumulator() {
        return new PrefixListAccumulator<>(getOrdering())
                .scanFrom(buildPrefixWatch());
    }

    @Override
    public Observable<? extends PrefixListDeltaAccumulator<T>> buildListDeltaAccumulator() {
        return new PrefixListDeltaAccumulator<>(getOrdering())
                .scanFrom(buildPrefixWatch());
    }
}
