module UserOnline
  class << self
    redis_config = YAML.load_file(Rails.root.join('config', 'redis.yml'))
    if redis_config.present?
      redis_url = redis_config[Rails.env]['url']
      $redis = Redis.new({:url=>redis_url})
    else
      $redis = Rails.cache.data
    end
    def login(user_id)
      set_bit(user_id, 1)
    end

    def logout(user_id)
      if Rails.cache.is_a?(ActiveSupport::Cache::RedisStore)
        now = Time.now()
        keys = []
        (1..5).each do |i|
          key = (now - i.minutes).strftime("%H-%M")
          keys << "cache:online_user_#{key}"
          set_bit_and_expire(cache_key, user_id, 0) unless $redis.ttl(cache_key) == -2
        end
      end
      set_bit(user_id, 0)
    end

    def set_bit(user_id, flag)
      if $redis.ttl(cache_key) == -2
        # 如果key不存在
        set_bit_and_expire(cache_key, user_id, flag)
      else
        if $redis.ttl(cache_key) ==-1
          # 可以存在，但过期时间没关联
          # 这种情况大概率是并发原因导致对相应key设置过期时跳过了。所以删除并重新设置过期时间
          $redis.del(cache_key)
          set_bit_and_expire(cache_key, user_id, flag)
        end

        # 统计当前时间下，前5分钟的活跃人数
        $redis.setbit(cache_key, user_id, flag)
      end
    end

    def set_bit_and_expire(cache_key, user_id, flag)
      $redis.setbit(cache_key, user_id, flag)
      # $redis.setbit(last_cache_key, user_id, flag)
      # 现在统计5分钟在线人数，这里设置6分钟过期，目的是统计当前时刻的前5分钟
      $redis.expire(cache_key, 6 * 60)
    end

    def count
      if Rails.cache.is_a?(ActiveSupport::Cache::RedisStore)
        now = Time.now()
        keys = []
        (0..4).each do |i|
          key = (now - i.minutes).strftime("%H-%M")
          keys << "cache:online_user_#{key}"
        end
        # 防止每个分钟数据有重复，所以去重去除
        $redis.bitop("OR", "daiao", keys)
        $redis.bitcount("daiao")
      else
        0
      end
    end

    def cache_key
      if Rails.cache.is_a?(ActiveSupport::Cache::RedisStore)
        "cache:online_user_#{Time.now().strftime("%H-%M")}"
      else
        raise '请配置config.cache_store = redis_store'
      end
    end

    def last_cache_key
      if Rails.cache.is_a?(ActiveSupport::Cache::RedisStore)
        # 如设置5分钟内即300秒有请求的用户视为在线, 则最大会统计到10分钟内有活动用户
        # TODO 更精确时长
        begin_hour = Time.now.beginning_of_hour
        minutes_piece = (Time.now - begin_hour) / (60 * 5)
        time = begin_hour.since((minutes_piece.to_i - 1) * (60 * 5)).strftime("%H-%M")
        "cache:online_user_#{time}"
      else
        raise '请配置config.cache_store = redis_store'
      end
    end

  end
end
