<?php

namespace Api\PhpUtils\Lock;

/**
 * Redis 频率锁
 */
use Api\PhpUtils\Redis\RedisUtil;

class FrequencyLockUtil
{

    const MIN_FREQUENCY_SECONDS = 3;   // 频率锁默认最小间隔秒数
    const MIN_FREQUENCY_TIMES   = 1;   // 频率锁默认最小间隔秒数内最大访问次数

    const PREFIX_FREQUENCY_LOCK = 'flk:';

    private static $handler = null;

    private static function initCache()
    {
        if (empty(self::$handler)){
            //获取连接句柄, 使用gateway的codis
            self::$handler = RedisUtil::getInstance('cache', ['serializer' => 'none']);
        }
    }

    /**
     * 频率锁, 每$expire秒钟允许$times次$key访问
     *
     * @param string $key   锁定的key
     * @param int $times    允许访问次数
     * @param int $expire   锁定时长,秒数
     * @return boolean
     */
    public static function isLocked($key, $times = self::MIN_FREQUENCY_TIMES, $expire = self::MIN_FREQUENCY_SECONDS)
    {
        $key = self::PREFIX_FREQUENCY_LOCK . $key;
        self::initCache();
        $current_times = self::$handler->incr($key);
        if ($current_times == 1) {
            self::$handler->expire($key, $expire);
        }
        return ($current_times > $times) ? true : false;
    }
    
    /**
     * 频次减少
     * @param  string $key   锁定的key
     * @param  int $number   减少的值
     * @return void
     */
    public static function decr($key, $number = 1)
    {
        $key = self::PREFIX_FREQUENCY_LOCK . $key;
        self::initCache();
        return self::$handler->decrby($key, $number);
    }

    /**
     * 频次重置(测试用)
     * @param string $key
     */
    public static function reset($key)
    {
        $key = self::PREFIX_FREQUENCY_LOCK . $key;
        self::initCache();
        return self::$handler->del($key);
    }

    /**
     * 已经使用次数
     * @param string $key
     * @return int
     */
    public static function get($key)
    {
        $key = self::PREFIX_FREQUENCY_LOCK . $key;
        self::initCache();
        $times = self::$handler->get($key);
        return intval($times);
    }
}
