require 'optparse'
require 'socket'

def main(args = ARGV)
  options = {
    :type => :write,
    :sleep_interval => 1.0,
    :name => 'sally',
    :port => 22000
  }

  OptionParser.new do |opts|
    opts.banner = "Usage: ruby #{File.basename($0)} [options]"
    opts.on('-t [TYPE]', '--type [TYPE]', [:read, :write],
            "Client type (read/write), default=#{options[:type].to_s}") do |t|
      options[:type] = t
    end
    opts.on('-n [NAME]', '--name [NAME]',
            "Client (player) name, default='#{options[:name]}'") do |n|
      options[:name] = n
    end
    opts.on('-s [SLEEP_INTERVAL]', '--sleep [SLEEP_INTERVAL]',
            "Sleep interval between requests, " <<
            "default=#{options[:sleep_interval]}") do |s|
      options[:sleep_interval] = s.to_f
    end
    opts.on('-p [PORT]', '--port [PORT]', Integer,
            "Server port, default=#{options[:port]}") do |p|
      options[:port] = p
    end
  end.parse!(args)

  run_client(options)
end

def run_client(options)
  client_type = options.fetch(:type, :read)
  client_name = options.fetch(:name, 'sally')
  sleep_interval = options.fetch(:sleep_interval, 1.0)
  port = options.fetch(:port, 22000)

  puts "Starting #{client_type} client for '#{client_name}', " <<
       "interval=#{sleep_interval}, port=#{port}"

  successes = 0
  backoff = 0.5
  nextloc = [rand(0..99), rand(0..99)]
  loop do
    begin
      TCPSocket.open('127.0.0.1', port) do |sock|
        case client_type
        when :read
          sock.send("marco #{client_name}\n", 0)
          location = sock.recv(100).to_s.split[2,4].map(&:to_i)
          puts "marco #{client_name} -> #{location.first} #{location.last}"
        when :write
          sock.send("polo #{client_name} #{nextloc.first} #{nextloc.last}\n", 0)
          recv_loc = sock.recv(100).to_s.split.map(&:to_i)
          puts "polo #{client_name} #{nextloc.first} #{nextloc.last} " <<
               "-> #{recv_loc.first} #{recv_loc.last}"
          nextloc = recv_loc
        end
        sock.close
      end
      successes += 1
      backoff = 0.5
      sleep sleep_interval
    rescue
      puts "made it #{successes} times. sleeping #{backoff} secs"
      successes = 0
      sleep backoff
      backoff *= 2
    end
  end
end

if $0 == __FILE__
  main
end