# from procreate
require "yaml"
require "net/ftp"

namespace :db do
  desc "Launch database console."
  task :console => [:load_db_config] do
    case @db_config["adapter"]
    when "postgresql"
      # use .pgpass if you don't want to enter your password
      cmd = "psql #{@db_config["database"]} #{@db_config["username"]}"
      
    when "mysql"
      cmd = "mysql -u#{@db_config["username"]} --password #{@db_config["password"]} #{@db_config["database"]}"
      
    end
    exec cmd
  end

  task "load_db_config" do
    ENV["RAILS_ENV"] ||= "development"
    @db_config = YAML::load_file("#{RAILS_ROOT}/config/database.yml")[ENV["RAILS_ENV"]]
  end
  
  desc "Dump the database to an SQL file"
  task :dump => [:load_db_config] do
    ENV["RAILS_ENV"] ||= "development"
    exec "mysqldump --add-drop-table -e -u #{@db_config['username']} --password=#{@db_config['password']} #{@db_config['database']} > #{@db_config['database']}.sql"
  end

  # http://blog.craigambrose.com/articles/2007/03/01/a-rake-task-for-database-backups
  require 'find'
  desc "Backup the database to a file. Options: DIR=base_dir RAILS_ENV=production MAX=20" 
  task :backup => [:environment] do
    datestamp     = Time.now.strftime("%Y-%m-%d_%H-%M-%S")    
    base_path     = ENV["DIR"] || "db" 
    backup_base   = File.join(base_path, 'backup')
    backup_folder = File.join(backup_base, datestamp)
    backup_file   = File.join(backup_folder, "#{RAILS_ENV}_dump.sql.gz")    
    File.makedirs(backup_folder)    
    
    db_config     = ActiveRecord::Base.configurations[RAILS_ENV]    
    
    sh "mysqldump -u #{db_config['username']} -p#{db_config['password']} -Q --add-drop-table -O add-locks=FALSE -O lock-tables=FALSE #{db_config['database']} | gzip -c > #{backup_file}"     
    puts "Created backup: #{backup_file}"     
    
    # # cleanup unwanted backups
    dir              = Dir.new(backup_base)
    all_backups      = dir.entries[2..-1].sort.reverse
    max_backups      = ENV["MAX"] && ENV["MAX"].to_i || 20
    unwanted_backups = all_backups[max_backups..-1] || []
    
    for unwanted_backup in unwanted_backups
      FileUtils.rm_rf(File.join(backup_base, unwanted_backup))
      puts "deleted #{unwanted_backup}" 
    end
    
    puts "Deleted #{unwanted_backups.length} backups, #{all_backups.length - unwanted_backups.length} backups available" 
  end
  
  namespace :backup do
    task :load_backup_config do
      @backup_config = YAML::load_file("#{RAILS_ROOT}/config/backup.yml")
    end

    
    task :create => [:load_db_config] do
      datestamp     = Time.now.strftime("%Y-%m-%d_%H-%M-%S")    
      base_path     = ENV["DIR"] || "db" 
      backup_base   = File.join(base_path, 'backup')
      backup_folder = File.join(backup_base, datestamp)
      @backup_file   = File.join(backup_folder, "#{RAILS_ENV}_dump.sql.gz")    
      File.makedirs(backup_folder)    

      db_config     = @db_config   

      cmd = "mysqldump -u #{db_config['username']} -p#{db_config['password']} -Q --add-drop-table -O add-locks=FALSE -O lock-tables=FALSE #{db_config['database']}"
      cmd << ' --verbose' if Rake.application.options.trace  
      cmd << " | gzip -c > #{@backup_file}"     
      system cmd
      
      if File.exist?(@backup_file)
        puts "Created backup: #{@backup_file}" if Rake.application.options.trace    
      else
        raise "No backup created"
      end
      
      Rake::Task['db:backup:delete_unwanted_backups'].invoke
    end
    
    desc "Delets unwanted local backups. Options: DIR=base_dir RAILS_ENV=production MAX=20"
    task :delete_unwanted_backups do
      base_path     = ENV["DIR"] || "db" 
      backup_base   = File.join(base_path, 'backup')
    
      dir              = Dir.new(backup_base)
      all_backups      = dir.entries[2..-1].sort.reverse
      max_backups      = ENV["MAX"] && ENV["MAX"].to_i || 20
      unwanted_backups = all_backups[max_backups..-1] || []
    
      for unwanted_backup in unwanted_backups
        FileUtils.rm_rf File.join(backup_base, unwanted_backup),
                        :verbose => Rake.application.options.trace
        puts "Deleted #{unwanted_backup}" if Rake.application.options.trace
      end
    
      puts "Deleted #{unwanted_backups.length} backups, #{all_backups.length - unwanted_backups.length} backups available" if Rake.application.options.trace
    end
    
    desc "Transfer backup the Database to a remote FTP server"
    task :to_ftp => [:create, :load_backup_config] do

      remote_filename = Date.new.strftime(@backup_config['remote_file_name']).downcase 

      Net::FTP.open(@backup_config['host'], @backup_config['username'], @backup_config['password']) do |ftp|
        ftp.putbinaryfile(@backup_file, remote_filename)
        puts "Uploaded %s to %s" % [remote_filename, @backup_config['host']] if Rake.application.options.trace
      end      
    end
    
  end # NS backup
end # NS db
