namespace :pg do
  # Creates a new backup on heroku, downloads that backup to latest.dump, and then calls pg:load
  #
  # bundle exec rake pg:pull
  # bundle exec rake pg:pull[staging]
  desc 'Pulls a newly captured backup from heroku (--remote heroku by default) and calls pg:load'
  task :pull, [:remote] => :environment do |t, args|
    args.with_defaults(:remote => 'heroku')

    puts "=== Pulling remote '#{args.remote}' database into latest.dump"

    Bundler.with_clean_env do
      unless system("heroku pg:backups:capture --remote #{args.remote}")
        puts "Error capturing heroku backup"
        exit
      end

      if system("curl -o latest.dump `heroku pg:backups:public-url --remote #{args.remote}`")
        puts "Downloading database completed"
      else
        puts "Error downloading database"
        exit
      end
    end

    Rake::Task['pg:load'].invoke
  end

  # Drops and re-creates the local database then initializes database with latest.dump
  #
  # bundle exec rake pg:load => Will replace the current database with latest.dump
  # bundle exec rake pg:load[something.dump] => Will replace the current database with something.dump
  desc 'Loads a postgresql .dump file into the development database (latest.dump by default)'
  task :load, [:file_name] => :environment do |t, args|
    args.with_defaults(:file_name => 'latest.dump')
    db = ActiveRecord::Base.configurations[Rails.env]

    puts "=== Loading #{args.file_name} into local '#{db['database']}' database"

    # bin/rails db:environment:set RAILS_ENV=development
    if Rails.env != 'production'
      ENV['DISABLE_DATABASE_ENVIRONMENT_CHECK'] = '1'
    end

    Rake::Task['db:drop'].invoke
    Rake::Task['db:create'].invoke

    if system("pg_restore --no-acl --no-owner --clean --if-exists -h localhost -U #{db['username']} -d #{db['database']} #{args.file_name}")
      puts "Loading database completed"
    else
      puts "Error loading database"
    end
  end

  # bundle exec rake pg:save => Will dump the database to latest.dump
  # bundle exec rake pg:save[something.dump] => Will dump the database to something.dump
  desc 'Saves the development database to a postgresql .dump file (latest.dump by default)'
  task :save, [:file_name] => :environment do |t, args|
    args.with_defaults(:file_name => 'latest.dump')
    db = ActiveRecord::Base.configurations[Rails.env]

    puts "=== Saving local '#{db['database']}' database to #{args.file_name}"

    if system("pg_dump -Fc --no-acl --no-owner -h localhost -U '#{db['username']}' '#{db['database']}' > #{args.file_name}")
      puts "Saving database completed"
    else
      puts "Error saving database"
    end
  end

  desc 'Clones the production (--remote heroku by default) database to staging (--remote staging by default)'
  task :clone, [:source_remote, :target_remote] => :environment do |t, args|
    args.with_defaults(:source_remote => 'heroku', :target_remote => 'staging')
    db = ActiveRecord::Base.configurations[Rails.env]

    puts "=== Cloning remote '#{args.source_remote}' to '#{args.target_remote}'"

    Bundler.with_clean_env do
      unless system("heroku pg:backups:capture --remote #{args.source_remote}")
        puts "Error capturing heroku backup"
        exit
      end

      url = (`heroku pg:backups:public-url --remote #{args.source_remote}`).chomp

      unless (url || '').length > 0
        puts "Error reading public-url from remote #{args.source_remote}"
        exit
      end

      unless system("heroku pg:backups:restore '#{url}' DATABASE_URL --remote #{args.target_remote}")
        puts "Error cloning heroku backup"
        exit
      end
    end

    puts 'Cloning database complete'
  end

end