namespace :rubber do
  namespace :util do
  
    rubber.allow_optional_tasks(self)
   
    desc <<-DESC
      Backup database using rake task rubber:backup_db
    DESC
    task :backup do
      master_instances = rubber_instances.for_role('db', :primary => true)
      slaves = rubber_instances.for_role('db', {})

      # Select only one instance for backup.  Favor slave database.
      selected_db_instance = (slaves+master_instances).first
            
      task_name = "_backup_db_#{selected_db_instance.full_name}".to_sym()
      task task_name, :hosts => selected_db_instance.full_name do
        rsudo "cd #{current_path} && RUBBER_ENV=#{RUBBER_ENV} BACKUP_DIR=/mnt/db_backups DBUSER=#{rubber_env.db_user} DBPASS=#{rubber_env.db_pass} DBNAME=#{rubber_env.db_name} DBHOST=#{selected_db_instance.full_name} rake rubber:backup_db"
      end
      send task_name
    end
    
    desc <<-DESC
      Restore database from s3 using rake task rubber:restore_db_s3
    DESC
    task :restore_s3 do
      master_instances = rubber_instances.for_role('db', :primary => true)
      slaves = rubber_instances.for_role('db', {})

      for instance in master_instances+slaves
        task_name = "_restore_db_s3_#{instance.full_name}".to_sym()
        task task_name, :hosts => instance.full_name do
          rsudo "cd #{current_path} && RUBBER_ENV=#{RUBBER_ENV} BACKUP_DIR=/mnt/db_backups DBUSER=#{rubber_env.db_user} DBPASS=#{rubber_env.db_pass} DBNAME=#{rubber_env.db_name} DBHOST=#{instance.full_name} rake rubber:restore_db_s3"
        end
        send task_name
      end
    end    
    
    desc <<-DESC
      Overwrite ec2 production database with export from local production database.
    DESC
    task :local_to_ec2 do
      require 'yaml'      
      master_instances = rubber_instances.for_role('db', :primary => true)
      slaves = rubber_instances.for_role('db', {})

      # Select only one instance for backup.  Favor slave database.
      selected_db_instance = (slaves+master_instances).first
            
      task_name = "_load_local_to_#{selected_db_instance.full_name}".to_sym()
      task task_name, :hosts => selected_db_instance.full_name do

        # Dump Local to tmp folder
        filename = "#{application}.local.#{Time.now.to_i}.sql.gz" 
        backup_file = "/tmp/#{filename}" 
        on_rollback { delete file }
        FileUtils.mkdir_p(File.dirname(backup_file))

        # Use database.yml to get connection params
        db = YAML::load(ERB.new(IO.read(File.join(File.dirname(__FILE__), '..','database.yml'))).result)[RUBBER_ENV]
        user = db['username']
        pass = db['passsword']
        pass = nil if pass and pass.strip.size == 0
        host = db['host']
        name = db['database']
        
        raise "No db_backup_cmd defined in rubber.yml, cannot backup!" unless rubber_env.db_backup_cmd
        db_backup_cmd = rubber_env.db_backup_cmd.gsub(/%([^%]+)%/, '#{\1}')
        db_backup_cmd = eval('%Q{' + db_backup_cmd + '}')

        # dbdump (or backup app) needs to be in your path
        puts "Backing up database with command:"
        system(db_backup_cmd)
        puts "Created backup: #{backup_file}"

        # Upload Local to S3
        cloud_provider = rubber_env.cloud_providers[rubber_env.cloud_provider]
        s3_prefix = "db/"
        backup_bucket = cloud_provider.backup_bucket
        if backup_bucket
          AWS::S3::Base.establish_connection!(:access_key_id => cloud_provider.access_key, :secret_access_key => cloud_provider.secret_access_key)
          unless AWS::S3::Bucket.list.find { |b| b.name == backup_bucket }
            AWS::S3::Bucket.create(backup_bucket)
          end
          dest = "#{s3_prefix}#{File.basename(backup_file)}"
          puts "Saving db dump to S3: #{backup_bucket}:#{dest}"
          AWS::S3::S3Object.store(dest, open(backup_file), backup_bucket)
        end
        
        send :restore_s3

      end
      send task_name
    end    

  end
end