#!/usr/bin/env ruby

require 'fileutils'
include FileUtils::Verbose
require 'tins/go'
include Tins::GO
require 'utils'

SSH_CONFIG = <<SSH_CONFIG_END
# ~/.ssh/config

Host *
  ForwardX11 = yes
  ControlMaster auto
  ControlPath ~/.ssh/%r@%h:%p.sock
SSH_CONFIG_END

def usage
  puts <<EOT
Usage: #{File.basename($0)} [OPTS] [user@]remote[:port]"

OPTS is one of
  -N                     list all session names on the specified remote
  -n NAME                name of the multiplexer session to attach to (defaults to $USER)
  -t [HOST[:PORT]]       host:port to tunnel if different from LOCALPORT
  -m screen|tmux         use sshscreen or tmux as a terminal multiplexer
  -l LOCALPORT           the localport to forward to
  -C (ssh|rc)-default|rc output ssh or rc config file
  -h                     to display this help

EOT
  exit 1
end

config = Utils::Config::ConfigFile.new

arguments = ARGV
opts = go 'l:t:n:C:m:hN', arguments

case opts['C']
when 'ssh-default'
  puts SSH_CONFIG; exit
when 'rc-default'
  puts config.to_ruby; exit
when 'rc'
  config.configure_from_paths
  puts config.to_ruby; exit
end

config.configure_from_paths

usage if opts['h'] or arguments.size != 1

if multiplexer = opts['m']
  config.ssh_tunnel.terminal_multiplexer = multiplexer
end

user_remote = arguments.shift
user, remote, rport =
  case user_remote
  when /\A(?:([^@:]+)@)?([^@:]+)(?::(\d+))?\Z/
    user = $1 || ENV['USER']
    user.to_s.empty? and fail "user required to login"
    [ user, $2, $3 || '22' ]
  else
    usage
  end
lport = opts['l']
tunnel, tport = nil, nil
if tunnel_port = opts['t']
  case tunnel_port
  when /\A([^:]+)(?::(\d+))?\Z/
    tunnel, tport = $1, $2 || '22'
    lport ||= tport
  else
    usage
  end
else
  tunnel, tport = 'localhost', lport
end

ssh_dir = File.expand_path('~/.ssh')
mkdir_p ssh_dir
sock_file = "#{ssh_dir}/#{user}@#{remote}:#{rport}.sock"
if env_user = ENV['USER']
  opts['n'] ||= env_user
else
  opts['n'] ||= 'session'
end
if opts['N']
  exec "ssh -p #{rport} -S #{sock_file} #{user}@#{remote} #{config.ssh_tunnel.multiplexer_list}"
else
  env = []
  File.exist? sock_file and rm_f sock_file
  r = config.ssh_tunnel.copy_paste.full? do |t|
    env << "COPY_REMOTE_HOST_PORT='#{t.bind_address}:#{t.port}'"
    " -R #{t}"
  end
  env *= ' '
  if lport
    exec "ssh -p #{rport} -Mt -L localhost:#{lport}:#{tunnel}:#{tport}#{r} "\
      "-S #{sock_file} #{user}@#{remote} "\
        "'env #{env} #{config.ssh_tunnel.multiplexer_new(opts['n'])} || "\
        "#{config.ssh_tunnel.multiplexer_attach(opts['n'])}'"
  else
    exec "ssh -p #{rport} -Mt -S #{sock_file} #{user}@#{remote}#{r} "\
      "'env #{env} #{config.ssh_tunnel.multiplexer_new(opts['n'])} || "\
      "#{config.ssh_tunnel.multiplexer_attach(opts['n'])}'"
  end
end