require 'fingercap/recipes'
require 'fingercap/persistant_directory'

Capistrano::Configuration.instance(:must_exist).load do
  def _instances
    if ENV['INSTANCE']
      [ENV['INSTANCE']]
    elsif ENV['INSTANCES']
      ENV['INSTANCES'].split(' ')
    elsif variables[:instances_file]
      File.read(File.expand_path(variables[:instances_file], __FILE__)).split(/\s/).map { |i| i.strip }
    else
      puts "[!] Please set an :instances_file or pass the instances to operate on through INSTANCE or INSTANCES."
      exit -1
    end
  end
  
  def install_from_secure(path, remote_file_name, options={})
    sudo "scp #{remote_ssh_options} deploy@secure.callrecord.me:/home/deploy/#{path} #{remote_file_name}"
  end
  
  set :instances,        _instances
  set :primary_instance, instances.first
  
  default_run_options[:pty] = true
  
  set :runner,    'app'
  set :user,      'deploy'
  set :deploy_to, "/var/www/#{application}"
  
  set  :domain, primary_instance
  role :app,   *instances
  role :web,   *instances
  role :db,     primary_instance, :primary => true
  role :master, primary_instance
  
  set :remote_secure_key_file, '/home/deploy/.ssh/secure.key'
  set :remote_ssh_options,     "-o 'StrictHostKeyChecking no' -i #{remote_secure_key_file}"
  
  if variables[:deploy_key_file]
    if File.exist?(deploy_key_file)
      ssh_options[:keys] = [deploy_key_file]
    else
      puts "[!] Can't read `#{deploy_key_file}', maybe certain volumes aren't mounted?"
      exit -1
    end
  else
    puts "[!] Please set :ssh_key_file with a path to a valid SSH key for the deploy user."
  end
  
  namespace :key do
    desc "Push the secure SSH key to the instance"
    task :push do
      remote_secure_key_dir = File.dirname(remote_secure_key_file)
      sudo "mkdir -p #{remote_secure_key_dir}"
      sudo "chown -R deploy:deploy #{remote_secure_key_dir}"
      sudo "rm -f #{remote_secure_key_file}"
      upload(secure_key_file, remote_secure_key_file)
      sudo "chmod 400 #{remote_secure_key_file}"
    end
    
    desc "Remove the secure SSH key from the instance"
    task :remove do
      sudo "rm -f #{remote_secure_key_file}"
    end
  end
  
  namespace :configure do
    desc "Set permissions on the application install directories"
    task :set_permissions do
      try_sudo "chown -R #{user}:wheel #{deploy_to}"
      try_sudo "chown -R #{fetch(:runner, "app")}:wheel #{shared_path}"
    end
    
    desc "Create persistant directories"
    task :create_persistant_directories do
      raise "Overwrite this task for the specific application"
    end
    
    desc "Symlink persistant directories"
    task :symlink_persistant_directories do
      raise "Overwrite this task for the specific application"
    end
    
    desc "Copy credentials from the secure instance to the shared directory"
    task :install_credentials do
    end
    
    desc "Copy server certificates from the secure instance to /etc"
    task :install_certificates do
      # TODO: permissions
      install_from_secure 'etc/ssl/private/callmobe.pem',   '/etc/ssl/private/callmobe.pem'
      install_from_secure 'etc/ssl/private/callrecord.pem', '/etc/ssl/private/callrecord.pem'
      install_from_secure 'etc/ssl/certs/robin.crt',        '/etc/ssl/certs/robin.crt'
    end
    
    desc "Install all gems needed by the application"
    task :install_gems do
      sudo "gem install libxml-ruby --no-rdoc --no-ri"
      run "if [ -f #{current_path}/Rakefile ]; then cd #{current_path}; sudo rake gems:install RAILS_ENV=production; fi"
    end
    
    desc "Setup additional networking"
    task :networking do
    end
  end
  
  namespace :monit do
    desc "Restart services"
    task :restart do
      sudo "/usr/sbin/monit -c /etc/monitrc restart all"
    end
  end
  
  namespace :sphinx do
    desc "Stop Sphinx"
    task :stop, :roles => :master do
      config_file = "#{current_path}/config/production.sphinx.conf"
      sudo "touch #{config_file}"
      sudo "chown app:app #{config_file}"
      sudo "chown app:app #{current_path}/log"
      run "if [ -f #{current_path}/Rakefile ]; then cd #{current_path}; sudo -u app rake thinking_sphinx:stop RAILS_ENV=production; fi"
    end
    
    desc "Perform additional configuration for the search daemon"
    task :configure, :roles => :master do
      config_file     = "#{current_path}/config/environments/production.rb"
      new_config_file = "#{current_path}/config/environments/production.rb.tmp"
      run "cat #{config_file} | sed 's/ThinkingSphinx\..*//' > #{new_config_file}"
      run "mv #{new_config_file} #{config_file}"
      
      config_file     = "#{current_path}/config/sphinx.yml"
      new_config_file = "#{current_path}/config/sphinx.yml.tmp"
      run "cat #{config_file} | sed 's/address:.*/address: 0.0.0.0/' > #{new_config_file}"
      run "mv #{new_config_file} #{config_file}"
    end
    
    desc "Start the search daemon"
    task :start, :roles => :master do
      config_file = "#{current_path}/config/production.sphinx.conf"
      sudo "touch #{config_file}"
      sudo "chown app:app #{config_file}"
      sudo "chown app:app #{current_path}/log"
      run "if [ -f #{current_path}/Rakefile ]; then cd #{current_path}; sudo -u app rake thinking_sphinx:configure RAILS_ENV=production; fi"
      run "if [ -f #{current_path}/Rakefile ]; then cd #{current_path}; sudo -u app rake thinking_sphinx:start RAILS_ENV=production; fi"
    end
  end
  
  namespace :tunnel do
    PID_FILE = '/var/run/ssh-tunnel.pid'
    START_STOP_DAEMON = '/sbin/start-stop-daemon'
    SSH = '/usr/bin/ssh'
    
    desc "Setup SSH tunnels to the secure instance"
    task :setup do
      args = "#{remote_ssh_options} -L 35553:localhost:35553 deploy@depot.callrecord.me -N"
      sudo "#{START_STOP_DAEMON} --make-pidfile --pidfile #{PID_FILE}  --exec #{SSH} --background --start -- #{args} "
    end
    
    desc "Tear SSH tunnels to the secure instance down"
    task :teardown do
      sudo "echo"
      run "if [ -f #{PID_FILE} ]; then sudo #{START_STOP_DAEMON} --pidfile #{PID_FILE} --stop; fi"
    end
    
    desc "Stop and start the tunnel"
    task :restart do
      tunnel.teardown
      tunnel.setup
    end
    
    desc "Clean out the pidfile left by a crashed SSH tunnel"
    task :cleanup do
      sudo "rm -f #{PID_FILE}"
    end
  end
  
  namespace :deploy do
    desc "Stop the application (empty operation)"
    task :stop do
    end
    
    desc "Start the application"
    task :start do
      apache.restart
    end
    
    desc "Restart the application"
    task :restart do
      passenger.restart
    end
    
    desc "Configure the instance for this application and install it"
    task :install do
      setup
      configure.set_permissions
      check
      configure.create_persistant_directories
      key.push
      configure.install_credentials
      configure.install_certificates
      configure.networking
      key.remove
      update
      configure.install_gems
    end
    
    desc "Set the server into maintenance mode"
    task :start_maintenance do
      sudo "a2enmod rewrite"
      sudo "a2dissite storage mobile device"
      sudo "a2ensite maintenance"
      sudo "/etc/init.d/apache2 reload"
    end
    
    desc "Take the server out of maintenance mode"
    task :stop_maintenance do
      sudo "a2dismod rewrite"
      sudo "a2dissite maintenance"
      sudo "a2ensite storage mobile device"
      sudo "/etc/init.d/apache2 reload"
    end
  end
  
  after 'deploy:symlink',     'configure:symlink_persistant_directories'
  
  if variables[:prepare_tasks]
    before "deploy",            *prepare_tasks
    before "deploy:migrations", *prepare_tasks
  end
  
  if variables[:finalize_tasks]
    after "deploy",             *finalize_tasks
    after "deploy:migrations",  *finalize_tasks
  end
end