#!/usr/bin/env ruby
require 'open3'
require 'io/console'

unless `which heroku` =~ /heroku/
  puts "It looks like the heroku command line tool hasn't been installed yet.  Please install"
  puts "the Heroku Toolbelt from https://toolbelt.heroku.com, run 'heroku auth:login', and then"
  puts "run this script again."
  exit 1
end

def capture(cmd, opts = {})
  o, s = Open3.capture2e(cmd, opts)
  o.strip
end

def ask(question, opts = {})
  print question + " "
  STDOUT.flush
  (opts[:noecho] ? STDIN.noecho(&:gets) : gets).strip
end

def nag(question, opts = {})
  answer = ''
  while answer.length == 0
    answer = ask(question, opts)
  end
  answer
end

def yes?(question)
  ask(question + " (y/n)") =~ /^y/i
end

def grab_heroku_config!
  config_data = capture("heroku config -s")
  $config = {}
  if config_data !~ /has no config vars/
    config_data.split("\n").map do |line|
      next if line =~ /^\s*(#|$)/ # skip comments and empty lines
      first_equal_sign = line.index('=')
      $config[line.slice(0, first_equal_sign)] = line.slice(first_equal_sign + 1, line.length)
    end
  end
end

def set_value(key, value, options = {})
  if $config[key].nil? || $config[key] == '' || ($config[key] != value && options[:force] != false)
    puts "Setting #{key} to #{value}" unless options[:silent]
    puts capture("heroku config:set #{key}=#{value}")
    $config[key] = value
  end
end

unless File.exists?(File.expand_path("~/.netrc")) && File.read(File.expand_path("~/.netrc")) =~ /heroku/
  puts "It looks like you need to log in to Heroku.  Please run 'heroku auth:login' before continuing."
  exit 1
end

puts "Welcome #{`heroku auth:whoami`.strip}!  It looks like you're logged into Heroku."
puts

info = capture("heroku info")
if info =~ /No app specified/i
  puts "It looks like you don't have a Heroku app set up yet for this repo."
  puts "You can either exit now and run 'heroku create', or I can do it for you."
  if yes?("Would you like me to create a Heroku app for you now in this repo?")
    puts `heroku create`
    info = capture("heroku info")
  else
    puts "Okay, exiting so you can do it."
    exit 0
  end
end

app_name = info.scan(/http:\/\/([\w\d-]+)\.herokuapp\.com/).flatten.first

unless yes?("Your Heroku app name is #{app_name}.  Is this correct?")
  puts "Well, then I'm not sure what to do here, sorry."
  exit 1
end

grab_heroku_config!

if $config.length > 0
  puts
  puts "Your current Heroku config:"
  $config.each do |key, value|
    puts '  ' + key + ' ' * (25 - [key.length, 25].min) + '= ' + value
  end
end

unless $config['APP_SECRET_TOKEN']
  puts "Setting up APP_SECRET_TOKEN..."
  puts capture("heroku config:set APP_SECRET_TOKEN=`rake secret`")
end

unless $config['DOMAIN']
  set_value 'DOMAIN', "#{app_name}.herokuapp.com", force: false
  first_time = true
end

set_value 'BUILDPACK_URL', "https://github.com/ddollar/heroku-buildpack-multi.git"
set_value 'PROCFILE_PATH', "deployment/heroku/Procfile.heroku", force: false
set_value 'ON_HEROKU', "true"
set_value 'FORCE_SSL', "true"
set_value 'USE_GRAPHVIZ_DOT', 'dot'

unless $config['INVITATION_CODE']
  puts "You need to set an invitation code for your Huginn instance.  If you plan to share this instance, you will"
  puts "tell this code to anyone who you'd like to invite.  If you won't share it, then just set this to something"
  puts "that people will not guess."

  invitation_code = nag("What code would you like to use?")
  set_value 'INVITATION_CODE', invitation_code
end

unless $config['SMTP_DOMAIN'] && $config['SMTP_USER_NAME'] && $config['SMTP_PASSWORD'] && $config['SMTP_SERVER'] && $config['EMAIL_FROM_ADDRESS']
  puts "Okay, let's setup outgoing email settings.  The simplest solution is to use the free sendgrid Heroku addon."
  puts "If you'd like to use your own server, or your Gmail account, please see .env.example and set"
  puts "SMTP_DOMAIN, SMTP_USER_NAME, SMTP_PASSWORD, and SMTP_SERVER with 'heroku config:set'."
  if yes?("Should I enable the free sendgrid addon?")
    puts capture("heroku addons:add sendgrid")

    set_value 'SMTP_SERVER', "smtp.sendgrid.net", silent: true
    set_value 'SMTP_DOMAIN', "heroku.com", silent: true

    grab_heroku_config!
    set_value 'SMTP_USER_NAME', $config['SENDGRID_USERNAME'], silent: true
    set_value 'SMTP_PASSWORD', $config['SENDGRID_PASSWORD'], silent: true
  else
    puts "Okay, you'll need to set SMTP_DOMAIN, SMTP_USER_NAME, SMTP_PASSWORD, and SMTP_SERVER with 'heroku config:set' manually."
  end

  unless $config['EMAIL_FROM_ADDRESS']
    email = nag("What email address would you like email to appear to be sent from?")
    set_value 'EMAIL_FROM_ADDRESS', email
  end
end

if first_time
  puts "Restarting..."
  puts capture("heroku restart")

  puts "Done!"
  puts
  puts "Visit https://#{app_name}.herokuapp.com/users/sign_up and use the invitation code shown below:"
  puts
  puts "\t#{$config['INVITATION_CODE']}"

  exit
end

branch = capture("git rev-parse --abbrev-ref HEAD")
if yes?("Should I push your current branch (#{branch}) to heroku?")
  puts "This may take a moment..."
  puts capture("git push heroku #{branch}:master -f")

  puts "Running database migrations..."
  puts capture("heroku run rake db:migrate")

  puts
  puts
  puts "I can make an admin user on your new Huginn instance and setup some example Agents."
  if yes?("Should I create a new admin user and some example Agents?")
    seed_email = nag "Okay, what is your email address?"
    seed_username = nag "And what username would you like to login as?"
    seed_password = nag "Finally, what password would you like to use?", noecho: true
    puts "\nJust a moment..."

    capture("heroku run rake db:seed SEED_EMAIL=#{seed_email} SEED_USERNAME=#{seed_username} SEED_PASSWORD=#{seed_password}")
    puts
    puts
    puts "Okay, you should be all set!  Visit https://#{app_name}.herokuapp.com and login as '#{seed_username}' with your password."
  end
end

puts
puts "Done!"
