class ApiLimitService < ApplicationService
  Error = Class.new(StandardError)

  def initialize() end

  def call

  end

  # 时间窗口法
  def is_action_allowed?(user_id, action_key, period, max_count)
    key = "#{user_id}:#{action_key}"
    count = $redis_cache.multi do |multi|
      multi.incr(key)
      multi.expire(key, period)
    end
    count[0] <= max_count
  end

  # 漏桶法
  def is_action_allowed_bucket?(user_id, action_key, capacity, rate)
    key = "#{user_id}:#{action_key}"
    # now = (("%10.3f" % Time.now.to_f).to_f * 1000).to_i
    now = Time.now.to_i
    count = $redis_cache.multi do |multi|
      multi.zadd(key, now, SecureRandom.uuid.gsub("-", ""))
      multi.zremrangebyscore(key, 0, now - capacity)
      multi.zcard(key)
      multi.expire(key, (capacity / rate + 1).to_i)
    end
    # puts "count1==#{count}"
    # puts "count2==#{count[2]}"
    count[2] <= capacity
  end

  def is_action_allowed_aaa?(user_id, action_key, period, maxCount)
    key = "#{user_id}:#{action_key}"
    now = (("%10.3f" % Time.now.to_f).to_f * 1000).to_i
    count = $redis_cache.multi do |multi|
      # 添加命令
      multi.zadd(key, now, SecureRandom.uuid.gsub("-", ""))
      # 清楚无用数据
      multi.zremrangebyscore(key, 0, now - period * 1000)
      # 判断规定时间内请求数量
      multi.zcard(key)
      # 重新设置过期时间
      multi.expire(key, period + 1)
    end
    # puts "count1==#{count}"
    # puts "count2==#{count[2]}"
    count[2] <= maxCount
  end

  def sdfsf

    # 每秒钟漏斗的容量

    capacity = 10


    # 漏斗填充速度

    leak_rate = 0.3

    # 当前漏斗中的水量

    current_volume = 0

    # 上一次漏水的时间

    last_leak_time = Time.now.to_i

    funnel_name = "tests"

    # $redis_cache.hset(funnel_name, "volume", capacity)
    $redis_cache.hset(funnel_name, "last_leak_time", Time.now.to_i)

    # 构造事务命令

    # result = $redis_cache.multi do |pipe|
    #   # 把当前时间与上一次漏水时间的差值，作为漏斗流出水量
    #
    #   pipe.hget(funnel_name, "last_leak_time")
    #
    #   pipe.hset(funnel_name, "last_leak_time", Time.now.to_i)
    #
    #   pipe.hget(funnel_name, "volume")
    #
    #   pipe.hget(funnel_name, "capacity")
    #
    #   pipe.hget(funnel_name, "leak_rate")
    # end

    current_volume = $redis_cache.hget(funnel_name, "volume")
    last_leak_time = $redis_cache.hget(funnel_name, "last_leak_time")
    # 先漏水
    leaked_volume = (Time.now.to_i - last_leak_time.to_i) * leak_rate.to_f

    current_volume = [current_volume.to_f + leaked_volume, capacity.to_f].sort.first
    puts "current_volume====#{current_volume}"
    # 判断是否可以通过请求
    if current_volume >= 1
      $redis_cache.hset(funnel_name, "volume", current_volume.to_i - 1)
      # $redis_cache.hset(funnel_name, "last_leak_time", Time.now.to_i)
      true
    else
      false
    end

  end

  def done_test3
    100.times.each do |t|
      if t % 2== 0
        sleep(1)
      end
      puts "#{t}:res====#{sdfsf}"
    end
  end

  def done_test
    100.times.each do |t|
      if t % 10== 0
        sleep(5)
      end
      puts "#{t}:res====#{is_action_allowed_bucket?("123", "test2", 10, 0.2)}"
    end
  end

  def done_test2
    100.times.each do |t|
      sleep(1)
      puts "#{t}:res====#{is_action_allowed_aaa?("123", "test3", 10, 5)}"
    end
  end

end
