<?php

namespace tw\redis\traits;

use tw\redis\TwRedis;

trait SortedSetTrait
{

    /**
     * 添加/更新一个元素
     * 
     * @param string $val
     * @param float $score
     * @return int 0|1 1代表新增
     */
    public function zadd($word, $val, $score): int
    {
        return TwRedis::zAdd($this->key($word), $score, $val);
    }

    /**
     * 删除 1 个或多个元素
     */
    public function zrem($word, $members): int
    {
        if (is_array($members)) {
            return TwRedis::zRem($this->key($word), ...$members);
        } else {
            return TwRedis::zRem($this->key($word), $members);
        }
    }

    /**
     * 求一个元素的分数
     * 
     * @param string $member
     * @return float|bool 分数|失败
     */
    public function zscore($word, $member)
    {
        return TwRedis::zScore($this->key($word), $member);
    }

    /**
     * 求一个元素的排名
     * 
     * @param string $member
     * @return float 名次
     */
    public function zrank($word, $member): float
    {
        return TwRedis::zRank($this->key($word), $member);
    }

    /**
     * 求 zset 的基数
     */
    public function zcard($word): int
    {
        return TwRedis::zCard($this->key($word));
    }

    /**
     * 求分数在 $start,$end 之间的元素个数
     * 
     * @param float|string $start,$end: 也可以包括 +inf -inf 表示正负无穷
     * @return 
     */
    public function zcount($word, $start, $end): int
    {
        return TwRedis::zCount($this->key($word), $start, $end);
    }

    /**
     * 增加指定元素的分数
     */
    public function zincr_by($word, $member, $by): float
    {
        return TwRedis::zIncrBy($this->key($word), $by, $member);
    }

    /**
     * 弹出分数最大的几个
     */
    public function zpop_max($word, $num): array
    {
        return TwRedis::zPopMax($this->key($word), $num);
    }

    /**
     * 弹出分数最小的几个
     */
    public function zpop_min($word, $num): array
    {
        return TwRedis::zPopMin($this->key($word), $num);
    }

    /**
     * 返回分数在 $start, $end 之间的子集合
     * @param float|string $start, $end: 范围 +inf, -inf 也可以
     * @param array $options: 例子:
     * ['withscores' => TRUE]
     * ['limit' => [1, 1]]
     * ['withscores' => TRUE, 'limit' => [1, 1]]
     * @return
     */
    public function zrange_by_score($word, $start, $end, $options): array
    {
        return TwRedis::zRangeByScore($this->key($word), $start, $end, $options);
    }

    public function zrem_range_by_rank($word, $start, $end)
    {
        return TwRedis::zRemRangeByRank($this->key($word), $start, $end);
    }

    public function zrem_range_by_score($word, $start, $end)
    {
        return TwRedis::zRemRangeByScore($this->key($word), $start, $end);
    }
}
