#!/usr/bin/env ruby
#
# backlog      Startup script for the backlog application
#
# chkconfig: 345 88 12
# description: Backlog

$VERBOSE=true

require 'rubygems'
require 'fileutils'
require 'ftools'
require 'yaml'
require 'rbconfig'

APPLICATION = 'backlog'

STATUS_STOPPED = 0
STATUS_RUNNING = 1
STATUS_STALE = 2
STATUS_NOT_ROOT = 3

if gem = Gem::searcher.find(APPLICATION)
  INSTALL_DIR = "#{Gem.dir}/gems/#{APPLICATION}-#{gem.version}"
else
  INSTALL_DIR = "/usr/local/#{APPLICATION}/current"
end

config_file = Config::CONFIG["sysconfdir"] + '/backlog.conf'
config = File.open(config_file) {|f| YAML::load(f)} if File.exists? config_file
config ||= {}

LOG_DIR = "#{INSTALL_DIR}/log"
PID_FILE = '/var/run/backlog.pid'

def start(config)
  File.makedirs LOG_DIR unless File.exists? LOG_DIR
  File.makedirs File.dirname(PID_FILE) unless File.exists? File.dirname(PID_FILE)

  status = get_status
  case status
    when STATUS_RUNNING:
      puts "Process already running.  Stopping."
      exit 1
    when STATUS_STALE:
      puts "Deleting stale PID file."
      File.delete(PID_FILE)
    when STATUS_STOPPED:
    when STATUS_NOT_ROOT:
      puts "Permission denied.  Please run as root/administrator."
      exit 6
    else
      puts "Unknown status: #{status}.  Stopping"
      exit 2
  end
  Dir.chdir INSTALL_DIR
  ENV['RAILS_ENV'] = 'production'
  if defined? JRUBY_VERSION
    # `glassfish -p #{config['port'] || 3000} -e production -d -P #{PID_FILE} 1>#{LOG_DIR}/stdout.log 2>#{LOG_DIR}/stderr.log`
    `jruby -S trinidad -t -p #{config['port'] || 3000} -e production -ldaemon -d #{PID_FILE} 1>#{LOG_DIR}/stdout.log 2>#{LOG_DIR}/stderr.log`
  else
    `mongrel_rails start -p #{config['port'] || 3000} -e production -c #{INSTALL_DIR} -d -m #{INSTALL_DIR}/config/mime_types.yaml -P #{PID_FILE} 1>#{LOG_DIR}/stdout.log 2>#{LOG_DIR}/stderr.log`
  end
end

def stop(config)
  if File.exists? PID_FILE
    # `mongrel_rails stop -c #{INSTALL_DIR} -P #{PID_FILE}`
    system "kill `cat #{PID_FILE}`"
    File.delete PID_FILE
  else
    puts "#{APPLICATION} not running."
  end
end

def get_pid
  if File.exists? PID_FILE
    return File.readlines(PID_FILE)[0].to_i
  else
    return nil
  end
end

def get_status
  pid = get_pid
  if pid
    begin
      Process.kill(0, pid)
      return STATUS_RUNNING
    rescue Errno::ESRCH
      return STATUS_STALE
    rescue Errno::EPERM
      return STATUS_NOT_ROOT
    end
  else
    return STATUS_STOPPED
  end
end

# See how we were called.
case ARGV[0]
when 'start':
  start(config)
when 'stop':
  stop(config)
when 'restart':
  stop(config)
  start(config)
when 'reload':
  puts `mongrel_rails restart -c #{INSTALL_DIR} -P #{PID_FILE}`
when 'status'
  case get_status
  when STATUS_RUNNING:
    puts "#{APPLICATION} is running as pid #{get_pid}."
    exit 0
  when STATUS_STOPPED:
    puts "#{APPLICATION} is stopped."
    exit 5
  when STATUS_STALE:
    puts "#{APPLICATION} is stopped but PID file exists with pid #{get_pid}."
    exit 4
  when STATUS_NOT_ROOT:
    puts "Permission denied.  Please run as root/administrator."
    exit 6
  else
    puts "Unknown status #{get_status}."
    exit 3
  end
when 'setup_unix'
  puts "Starting setup on #{RUBY_PLATFORM}"
  bsd = ARGV[1..-1].include? 'bsd'
  debug = ARGV[1..-1].include? 'debug'
  pg_admin_user = bsd ? 'pgsql' : 'postgres'
  current_user = `whoami`
  users = `su - #{pg_admin_user} -c "echo '\\du' | psql template1"`
  raise "Could not list users: #{$? >> 8}:#{$? & 0xff}" unless ($? >> 8) == 0
  unless users =~ /root/
    puts users
    createuser_command = `which createuser`.chomp
    puts `su - #{pg_admin_user} -c "#{createuser_command} -dAR #{current_user}"`
  end
  dbs = `su - #{pg_admin_user} -c "echo '\\l' | psql template1"`
  unless dbs =~ /#{APPLICATION}_production/
    puts dbs
    createdb_command = `which createdb`.chomp
    puts `su - #{pg_admin_user} -c "#{createdb_command} #{APPLICATION}_production"`
    raise "Could not create database: #{$? >> 8}:#{$? & 0xff}" unless ($? >> 8) == 0
  end
  FileUtils.mkdir_p INSTALL_DIR
  Dir.chdir INSTALL_DIR
  Dir.mkdir LOG_DIR unless File.exists? LOG_DIR
  ENV['RAILS_ENV'] = 'production'
  puts `#{'jruby -S' if RUBY_PLATFORM =='java'} bundle install`
  puts `#{'jruby -S' if RUBY_PLATFORM =='java'} rake db:migrate #{'--trace' if debug}`
  raise "Could not migrate database: #{$? >> 8}:#{$? & 0xff}" unless ($? >> 8) == 0
  
  # TODO:  provide startup information based on launchd in OS X versions >= 10.4
  if File.directory? '/etc/init.d'
    startup_app = "/etc/init.d/#{APPLICATION}"
    File.delete startup_app if File.exists? startup_app
    `cp -p #{INSTALL_DIR}/bin/backlog_init.d #{startup_app}` unless File.exists? startup_app
    `chmod a+x #{startup_app}` if File.exists? startup_app
    (0..6).each do |run_level|
      link_name      = "/etc/rc#{run_level}.d/S88#{APPLICATION}"
      kill_link_name = "/etc/rc#{run_level}.d/K12#{APPLICATION}"
      if [3,4,5].include? run_level
        unless File.exists? link_name
          puts "Creating startup link for run level #{run_level}."
          `su - -c "ln -s /etc/init.d/#{APPLICATION} #{link_name}"`
        end
        if File.exists? kill_link_name
          puts "Removing kill link for run level #{run_level}."
          `su - -c "rm #{kill_link_name}"`
        end
      else
        if File.exists? link_name
          puts "Removing startup link for run level #{run_level}."
          `su - -c "rm #{link_name}"`
        end
        unless File.exists? kill_link_name
          puts "Creating kill link for run level #{run_level}."
          `su - -c "ln -s /etc/init.d/#{APPLICATION} #{kill_link_name}"`
        end
      end
    end
  end
  FileUtils.mkdir_p File.dirname(config_file)
  FileUtils.cp "#{INSTALL_DIR}/etc/#{APPLICATION}.conf", config_file unless File.exists? config_file
  puts
else
  puts "Usage: #$0 {start|stop|restart|status|setup_unix [bsd] [debug]}"
  exit 1
end

exit 0