package com.lambdaworks.redis.api.rx;

import java.util.List;
import java.util.Map;
import com.lambdaworks.redis.MapScanCursor;
import com.lambdaworks.redis.ScanArgs;
import com.lambdaworks.redis.ScanCursor;
import com.lambdaworks.redis.StreamScanCursor;
import com.lambdaworks.redis.output.KeyStreamingChannel;
import com.lambdaworks.redis.output.KeyValueStreamingChannel;
import com.lambdaworks.redis.output.ValueStreamingChannel;
import rx.Observable;

/**
 * Observable commands for Hashes (Key-Value pairs).
 * 
 * @param <K> Key type.
 * @param <V> Value type.
 * @author Mark Paluch
 * @since 4.0
 * @generated by com.lambdaworks.apigenerator.CreateReactiveApi
 */
public interface RedisHashReactiveCommands<K, V> {

    /**
     * Delete one or more hash fields.
     * 
     * @param key the key
     * @param fields the field type: key
     * @return Long integer-reply the number of fields that were removed from the hash, not including specified but non existing
     *         fields.
     */
    Observable<Long> hdel(K key, K... fields);

    /**
     * Determine if a hash field exists.
     * 
     * @param key the key
     * @param field the field type: key
     * @return Boolean integer-reply specifically:
     * 
     *         {@literal true} if the hash contains {@code field}. {@literal false} if the hash does not contain {@code field},
     *         or {@code key} does not exist.
     */
    Observable<Boolean> hexists(K key, K field);

    /**
     * Get the value of a hash field.
     * 
     * @param key the key
     * @param field the field type: key
     * @return V bulk-string-reply the value associated with {@code field}, or {@literal null} when {@code field} is not present
     *         in the hash or {@code key} does not exist.
     */
    Observable<V> hget(K key, K field);

    /**
     * Increment the integer value of a hash field by the given number.
     * 
     * @param key the key
     * @param field the field type: key
     * @param amount the increment type: long
     * @return Long integer-reply the value at {@code field} after the increment operation.
     */
    Observable<Long> hincrby(K key, K field, long amount);

    /**
     * Increment the float value of a hash field by the given amount.
     * 
     * @param key the key
     * @param field the field type: key
     * @param amount the increment type: double
     * @return Double bulk-string-reply the value of {@code field} after the increment.
     */
    Observable<Double> hincrbyfloat(K key, K field, double amount);

    /**
     * Get all the fields and values in a hash.
     * 
     * @param key the key
     * @return Map&lt;K,V&gt; array-reply list of fields and their values stored in the hash, or an empty list when {@code key}
     *         does not exist.
     */
    Observable<Map<K, V>> hgetall(K key);

    /**
     * Stream over all the fields and values in a hash.
     * 
     * @param channel the channel
     * @param key the key
     * 
     * @return Long count of the keys.
     */
    Observable<Long> hgetall(KeyValueStreamingChannel<K, V> channel, K key);

    /**
     * Get all the fields in a hash.
     * 
     * @param key the key
     * @return K array-reply list of fields in the hash, or an empty list when {@code key} does not exist.
     */
    Observable<K> hkeys(K key);

    /**
     * Stream over all the fields in a hash.
     * 
     * @param channel the channel
     * @param key the key
     * 
     * @return Long count of the keys.
     */
    Observable<Long> hkeys(KeyStreamingChannel<K> channel, K key);

    /**
     * Get the number of fields in a hash.
     * 
     * @param key the key
     * @return Long integer-reply number of fields in the hash, or {@code 0} when {@code key} does not exist.
     */
    Observable<Long> hlen(K key);

    /**
     * Get the values of all the given hash fields.
     * 
     * @param key the key
     * @param fields the field type: key
     * @return V array-reply list of values associated with the given fields, in the same
     */
    Observable<V> hmget(K key, K... fields);

    /**
     * Stream over the values of all the given hash fields.
     * 
     * @param channel the channel
     * @param key the key
     * @param fields the fields
     * 
     * @return Long count of the keys
     */
    Observable<Long> hmget(ValueStreamingChannel<V> channel, K key, K... fields);

    /**
     * Set multiple hash fields to multiple values.
     * 
     * @param key the key
     * @param map the null
     * @return String simple-string-reply
     */
    Observable<String> hmset(K key, Map<K, V> map);

    /**
     * Incrementally iterate hash fields and associated values.
     * 
     * @param key the key
     * @return MapScanCursor&lt;K, V&gt; map scan cursor.
     */
    Observable<MapScanCursor<K, V>> hscan(K key);

    /**
     * Incrementally iterate hash fields and associated values.
     * 
     * @param key the key
     * @param scanArgs scan arguments
     * @return MapScanCursor&lt;K, V&gt; map scan cursor.
     */
    Observable<MapScanCursor<K, V>> hscan(K key, ScanArgs scanArgs);

    /**
     * Incrementally iterate hash fields and associated values.
     * 
     * @param key the key
     * @param scanCursor cursor to resume from a previous scan, must not be {@literal null}
     * @param scanArgs scan arguments
     * @return MapScanCursor&lt;K, V&gt; map scan cursor.
     */
    Observable<MapScanCursor<K, V>> hscan(K key, ScanCursor scanCursor, ScanArgs scanArgs);

    /**
     * Incrementally iterate hash fields and associated values.
     * 
     * @param key the key
     * @param scanCursor cursor to resume from a previous scan, must not be {@literal null}
     * @return MapScanCursor&lt;K, V&gt; map scan cursor.
     */
    Observable<MapScanCursor<K, V>> hscan(K key, ScanCursor scanCursor);

    /**
     * Incrementally iterate hash fields and associated values.
     * 
     * @param channel streaming channel that receives a call for every key-value pair
     * @param key the key
     * @return StreamScanCursor scan cursor.
     */
    Observable<StreamScanCursor> hscan(KeyValueStreamingChannel<K, V> channel, K key);

    /**
     * Incrementally iterate hash fields and associated values.
     * 
     * @param channel streaming channel that receives a call for every key-value pair
     * @param key the key
     * @param scanArgs scan arguments
     * @return StreamScanCursor scan cursor.
     */
    Observable<StreamScanCursor> hscan(KeyValueStreamingChannel<K, V> channel, K key, ScanArgs scanArgs);

    /**
     * Incrementally iterate hash fields and associated values.
     * 
     * @param channel streaming channel that receives a call for every key-value pair
     * @param key the key
     * @param scanCursor cursor to resume from a previous scan, must not be {@literal null}
     * @param scanArgs scan arguments
     * @return StreamScanCursor scan cursor.
     */
    Observable<StreamScanCursor> hscan(KeyValueStreamingChannel<K, V> channel, K key, ScanCursor scanCursor, ScanArgs scanArgs);

    /**
     * Incrementally iterate hash fields and associated values.
     * 
     * @param channel streaming channel that receives a call for every key-value pair
     * @param key the key
     * @param scanCursor cursor to resume from a previous scan, must not be {@literal null}
     * @return StreamScanCursor scan cursor.
     */
    Observable<StreamScanCursor> hscan(KeyValueStreamingChannel<K, V> channel, K key, ScanCursor scanCursor);

    /**
     * Set the string value of a hash field.
     *
     * @param key the key
     * @param field the field type: key
     * @param value the value
     * @return Boolean integer-reply specifically:
     *
     *         {@literal true} if {@code field} is a new field in the hash and {@code value} was set. {@literal false} if
     *         {@code field} already exists in the hash and the value was updated.
     */
    Observable<Boolean> hset(K key, K field, V value);

    /**
     * Set the value of a hash field, only if the field does not exist.
     *
     * @param key the key
     * @param field the field type: key
     * @param value the value
     * @return Boolean integer-reply specifically:
     *
     *         {@code 1} if {@code field} is a new field in the hash and {@code value} was set. {@code 0} if {@code field}
     *         already exists in the hash and no operation was performed.
     */
    Observable<Boolean> hsetnx(K key, K field, V value);

    /**
     * Get the string length of the field value in a hash.
     *
     * @param key the key
     * @param field the field type: key
     * @return Long integer-reply the string length of the {@code field} value, or {@code 0} when {@code field} is not present
     *         in the hash or {@code key} does not exist at all.
     */
    Observable<Long> hstrlen(K key, K field);

    /**
     * Get all the values in a hash.
     *
     * @param key the key
     * @return V array-reply list of values in the hash, or an empty list when {@code key} does not exist.
     */
    Observable<V> hvals(K key);

    /**
     * Stream over all the values in a hash.
     *
     * @param channel streaming channel that receives a call for every value
     * @param key the key
     *
     * @return Long count of the keys.
     */
    Observable<Long> hvals(ValueStreamingChannel<V> channel, K key);
}
