<?php

namespace tw\redis\traits;

use tw\redis\TwRedis;

trait ListTrait
{
    /**
     * 头部插入一个或多个元素
     * 
     * @param int|string|array $vals: 待插入元素
     * @return int|bool: List 长度|false, 当 $word 存在并且构成的 key 不是 List 类型时失败
     */
    public function lpush($word, $vals)
    {
        if (is_array($vals)) {
            return TwRedis::lPush($this->key($word), ...$vals);
        } else {
            return TwRedis::lPush($this->key($word), $vals);
        }
    }

    /**
     * 从尾部追加元素
     * 
     * @param string|int|array $vals
     * @return int|bool: key 存在并且类型不为 List 时返回 false
     */
    public function rpush($word, $vals)
    {
        if (is_array($vals)) {
            return TwRedis::rPush($this->key($word), ...$vals);
        } else {
            return TwRedis::rPush($this->key($word), $vals);
        }
    }

    /**
     * 移除并返回 List 第一个元素
     * 
     * @param int|string $word: key 关键字
     * @return bool|string: 空 List 返回 false, 否则返回值
     */
    public function lpop($word)
    {
        return TwRedis::lPop($this->key($word));
    }

    /**
     * 返回并删除最后一个元素
     * 
     * @return string|bool: 空 List 返回 false
     */
    public function rpop($word)
    {
        return TwRedis::rPop($this->key($word));
    }

    public function lrange($word, $start, $stop): array
    {
        return TwRedis::lRange($this->key($word), $start, $stop);
    }

    /**
     * 删除指定元素(注意这个函数复杂度为O(n))
     * 
     * @param string $val: 元素值
     * @param int $num: 删除个数，0表示所有，负值表示从尾部开始删
     * @return int|bool: 删除个数|false 
     */
    public function lrem($word, $val, $num)
    {
        return TwRedis::lRem($this->key($word), $val, $num);
    }

    /**
     * 从头部删除指定个数的元素
     * 
     * @param int $start
     * @param int $stop
     * @return array|bool: 已删元素|失败 
     */
    public function ltrim($word, $start, $stop)
    {
        return TwRedis::lTrim($this->key($word), $start, $stop);
    }

    /**
     * 插入 $val 到 $pivot 后
     * 
     * @return int: -1 表示 $pivot 未找到
     */
    public function linsert_after($word, $pivot, $val): int
    {
        return TwRedis::lInsert($this->key($word), \Redis::AFTER, $pivot, $val);
    }

    /**
     * 插入 $val 到 $pivot 前
     * 
     * @return int: -1 表示 $pivot 未找到
     */
    public function linsert_before($word, $pivot, $val): int
    {
        return TwRedis::lInsert($this->key($word), \Redis::BEFORE, $pivot, $val);
    }

    /**
     * 求长度
     * 
     * @return int|bool: 长度|失败(当 key 不是 List)
     */
    public function llen($word)
    {
        return TwRedis::lLen($this->key($word));
    }
}
