#!/usr/bin/env ruby

require "redis"
require "optparse"
require 'nchan_tools/rdsck'

opt = {
  url: "redis://127.0.0.1:6379/",
  verbose: false,
  command: nil
}

opt_parser=OptionParser.new do |opts|
  opts.on("--url", "--url REDIS_URL (#{opt[:url]})", "Redis server and port..") do |v|
    opt[:url]=v
  end
  opts.on("-q", "--quiet", "output only results without any other information") do
    opt[:quiet]=true
  end
  opts.on("--list-channels", "list all Nchan channels on Redis server or cluster") do |v|
    opt[:command]=:filter_channels
  end
  opts.on("--watch-channels", "watch for changes in Nchan channels on Redis server or cluster") do |v|
    opt[:command]=:watch_channels
  end
  opts.on("--set-notify-keyspace-events", "when using --watch-channels, sets the notify-keyspace-events Redis config before starting. May not be possible if the redis 'config' command is disabled") do
    opt[:set_notify_keyspace_events] = true
end
  opts.on("--filter-channels-min-subscribers=[NUMBER]") do |v|
    opt[:command]||=:filter_channels
    opt[:min_subscribers]=v.to_i
  end
end
opt_parser.banner= <<~EOB
  Debugging tools for the Redis server or cluster backing Nchan.
  Usage: nchan-redis-debug [options]
  
  WARNING: --list-channels and --filter-channels-* options for this tool
    use the Redis SCAN command. This may increase CPU load on the Redis 
    server and may affect the latency of Nchan requests.
    USE THESE OPTIONS WITH GREAT CARE
    
  Example:
    nchan-redis-debug --url redis:// --filter-channels-min-subscribers=10
EOB
opt_parser.parse!

opt[:verbose] = !opt[:quiet]

rdsck = Rdsck.new opt
if not rdsck.connect
  STDERR.puts "failed to connect to #{opt[:url]}"
  exit 1
end

case opt[:command]
when :filter_channels
  rdsck.dbg "scanning for channels #{opt[:min_subscribers] && "with subscribers >= #{opt[:min_subscribers]}"}"
  chans = rdsck.filter_channels(min_subscribers: opt[:min_subscribers])
  rdsck.dbg "found #{chans.count} channel#{chans.count != 1 && "s"}#{chans.count == 0 ? "." : ":"}"
  puts chans.join("\n")
when :watch_channels
  rdsck.dbg "watching for channels #{opt[:min_subscribers] && "with subscribers >= #{opt[:min_subscribers]}"}"
  rdsck.watch_channels({min_subscribers: opt[:min_subscribers]}, opt[:set_notify_keyspace_events])
else
  puts "Nothing to do"
end
