#!/usr/bin/ruby
require 'rubygems'
require 'appscript'
require 'optparse'

options = {}

rows = nil
columns = nil

optparse = OptionParser.new do |opts|
  opts.banner = "Usage: #{File.basename(__FILE__)} [options]"
  options[:debug] = false
  options[:fullscreen] = false
  opts.on('-d', '--debug', "Start RIPL after creating terminals") { options[:debug] = true }
  opts.on('-f', '--file FILE', "Cluster file") { |f| options[:file] = f }
  opts.on('-F', '--fullscreen', "Fullscreen") { options[:fullscreen] = true }
  opts.on('-g', '--grid WxH', "Grid size") { |f| options[:grid] = f.split("x")}
  opts.on('-u', '--username USERNAME', "SSH username") { |u| options[:username] = u }
  opts.on('-c', '--cluster CLUSTERNAME', "Name of the cluster specified in ~/.i2csshrc") { |c| options[:cluster] = c }
end

optparse.parse!

unless options[:file] || options[:grid] || options[:cluster] then
  puts optparse.help
  exit
end

if options[:file]  && options[:grid] then
  puts "ERROR: -g and -f can't be used at the same time"
  puts optparse.help
  exit
end

ssh_prefix = "ssh " + (options[:username] ? "#{options[:username]}@" : "")

if options[:file] then
  servers = File.read(options[:file]).split("\n")
elsif options[:grid] then
  columns = options[:grid][0].to_i
  rows = options[:grid][1].to_i
elsif options[:cluster] then
  require 'yaml'
  config_hash = YAML.load(File.read(File.expand_path("~/.i2csshrc")))
  servers = config_hash["clusters"][options[:cluster]]
end

count = servers.size
rows ||= Math.sqrt(count).ceil
columns ||= (count / rows.to_f).ceil

iterm = Appscript.app.by_name('iTerm')
finder = Appscript.app.by_name('Finder')
sys_events = Appscript.app.by_name('System Events')

window_bounds = finder.desktop.window.bounds

term = iterm.make(:new => :terminal)
session = term.sessions.after.make(:new => :session)
session.exec(:command => "/bin/bash -l")

if options[:fullscreen] then
  window = iterm.windows.get.sort_by{|x| x.id_.get}.last
  window.bounds.set(window_bounds.get)
end

(columns - 1).times do
  sys_events.keystroke("d", :using => :command_down)
end
(rows - 1).times do
  (columns - 1).times do
    sys_events.key_code(123, :using => [:command_down, :option_down])
  end
  (columns).times do |x|
    sys_events.keystroke("D", :using => :command_down)
    sys_events.key_code(124, :using => [:command_down, :option_down]) unless (columns - 1) == x
  end
end

(rows * columns).times do |i|
    term.sessions[i+1].write(:text => "#{ssh_prefix}#{servers[i]}") if servers && servers[i]
end
if options[:debug] then
  require 'ripl'
  Ripl.start :binding => binding
end