require 'hipchat'

namespace :hipchat do

  task :notify_deploy_started do
    send_message("#{human} is deploying #{deployment_name} to #{environment_string}.", send_options)
  end

  task :notify_deploy_finished do
    send_options.merge!(:color => success_message_color)
    send_message("#{human} finished deploying #{deployment_name} to #{environment_string}.", send_options)
  end

  task :notify_deploy_reverted do
    send_options.merge!(:color => failed_message_color)
    send_message("#{human} cancelled deployment of #{deployment_name} to #{environment_string}.", send_options)
  end

  def send_options
    return @send_options if defined?(@send_options)
    @send_options = message_format ? {:message_format => message_format } : {}
    @send_options.merge!(:notify => message_notification)
    @send_options.merge!(:color => message_color)
    @send_options
  end

  def send_message(message, options)
    return unless enabled?

    hipchat_token = fetch(:hipchat_token)
    hipchat_room_name = fetch(:hipchat_room_name)
    hipchat_options = fetch(:hipchat_options, {})

    hipchat_client = fetch(:hipchat_client, HipChat::Client.new(hipchat_token, hipchat_options))

    if hipchat_room_name.is_a?(String)
      rooms = [hipchat_room_name]
    elsif hipchat_room_name.is_a?(Symbol)
      rooms = [hipchat_room_name.to_s]
    else
      rooms = hipchat_room_name
    end

    rooms.each { |room|
      begin
        hipchat_client[room].send(deploy_user, message, options)
      rescue => e
        puts e.message
        puts e.backtrace
      end
    }
  end

  def enabled?
    fetch(:hipchat_enabled, true)
  end

  def environment_string
    if fetch(:stage)
      "#{fetch(:stage)} (#{environment_name})"
    else
      environment_name
    end
  end

  def deployment_name
    if fetch(:branch, nil)
      branch = fetch(:branch)
      real_revision = fetch(:real_revision)

      name = "#{application_name}/#{branch}"
      name += " (revision #{real_revision[0..7]})" if real_revision
      name
    else
      application_name
    end
  end

  def application_name
    alt_application_name.nil? ? fetch(:application) : alt_application_name
  end

  def message_color
    fetch(:hipchat_color, 'yellow')
  end

  def success_message_color
    fetch(:hipchat_success_color, 'green')
  end

  def failed_message_color
    fetch(:hipchat_failed_color, 'red')
  end

  def message_notification
    fetch(:hipchat_announce, false)
  end

  def message_format
    fetch(:hipchat_message_format, 'html')
  end

  def deploy_user
    fetch(:hipchat_deploy_user, 'Deploy')
  end

  def alt_application_name
    fetch(:hipchat_app_name, nil)
  end

  def human
    user = ENV['HIPCHAT_USER'] || fetch(:hipchat_human)
    user = user || if (u = %x{git config user.name}.strip) != ''
                     u
                   elsif (u = ENV['USER']) != ''
                     u
                   else
                     'Someone'
                   end
    user
  end

  def environment_name
    fetch(:hipchat_env, fetch(:rack_env, fetch(:rails_env, fetch(:stage))))
  end

  before 'deploy:starting', 'hipchat:notify_deploy_started'
  after 'deploy:finished', 'hipchat:notify_deploy_finished'
  if Rake::Task.task_defined? 'deploy:failed'
    after 'deploy:failed', 'hipchat:notify_deploy_reverted'
  end

end
