module Sinatra
  module MemcachedInspector
    def memcached_inspect options
      host = options[:host]
      port = options[:port]
      key = options[:key]
      query = options[:query]
      limit = options[:limit]
      page = options[:page]
      per_page = options[:per_page]

      inspect = inspector host, port

      # Filter by key if defined
      inspect = inspect.select{|pair| pair[:key] == key }.first if !key.nil?

      # Filter keys by query/regexp
      inspect = inspect.select{|pair| pair[:key] =~ Regexp.new(query, 'i') } if !query.nil?

      # Filter keys by limit
      inspect = inspect.take(limit.to_i) if !limit.nil?

      # Filter keys by pagination
      if !page.nil?
        per_page = per_page.to_i
        page = page.to_i

        index_first = inspect.size/per_page * page
        index_last = index_first + per_page
        inspect = inspect[index_first...index_last]
      end

      inspect
    end

    private
    def inspector host, port
      # Looks horrible, got it from a gist... yet, it works.

      keys = []
      cache_dump_limit = 9_000 # It's over...

      localhost = Net::Telnet::new("Host" => host, "Port" => port, "Timeout" => 3)
      slab_ids = []

      localhost.cmd("String" => "stats items", "Match" => /^END/) do |c|
        matches = c.scan(/STAT items:(\d+):/)
        slab_ids = matches.flatten.uniq
      end

      slab_ids.each do |slab_id|
        localhost.cmd("String" => "stats cachedump #{slab_id} #{cache_dump_limit}", "Match" => /^END/) do |c|
          matches = c.scan(/^ITEM (.+?) \[(\d+) b; (\d+) s\]$/).each do |key_data|
            (cache_key, bytes, expires_time) = key_data
            expires_in = expires_time.to_i
            infinite = false
            infinite = true if Time.at(expires_time.to_i) < Time.now

            keys << { key: cache_key, bytes: bytes, expires_in: expires_in, infinite: infinite }
          end
        end
      end

      keys
    end
  end
end

