#!/usr/bin/ruby

require "optparse"

module Sensu
  class Install
    class << self
      def cli_options(arguments=ARGV)
        options = {
          :verbose => false,
          :plugins => []
        }
        optparse = OptionParser.new do |opts|
          opts.on("-h", "--help", "Display this message") do
            puts opts
            exit
          end
          opts.on("-v", "--verbose", "Enable verbose logging") do
            options[:verbose] = true
          end
          opts.on("-p", "--plugin PLUGIN", "Install a Sensu PLUGIN") do |plugin|
            options[:plugins] << plugin
          end
          opts.on("-P", "--plugins PLUGIN[,PLUGIN]", "PLUGIN or comma-delimited list of Sensu plugins to install") do |plugins|
            options[:plugins].concat(plugins.split(","))
          end
          opts.on("-s", "--source SOURCE", "Install Sensu plugins from a custom SOURCE") do |source|
            options[:source] = source
          end
        end
        optparse.parse!(arguments)
        options
      end

      def log(message)
        puts "[SENSU-INSTALL] #{message}"
      end

      def plugin_gem_installed?(raw_gem, options={})
        log "determining if Sensu plugin gem '#{raw_gem}' is already installed ..."
        gem_name, gem_version = raw_gem.split(":")
        gem_command = "gem list -i #{gem_name}"
        gem_command << " --version '#{gem_version}'" if gem_version
        log gem_command if options[:verbose]
        if system(gem_command)
          log "Sensu plugin gem '#{gem_name}' has already been installed"
          true
        else
          log "Sensu plugin gem '#{gem_name}' has not been installed" if options[:verbose]
          false
        end
      end

      def install_plugin_gem(raw_gem, options={})
        log "installing Sensu plugin gem '#{raw_gem}'"
        gem_name, gem_version = raw_gem.split(":")
        gem_command = "gem install #{gem_name}"
        gem_command << " --version '#{gem_version}'" if gem_version
        gem_command << " --no-ri --no-rdoc"
        gem_command << " --verbose" if options[:verbose]
        gem_command << " --source #{options[:source]}" if options[:source]
        log gem_command if options[:verbose]
        unless system(gem_command)
          log "failed to install Sensu plugin gem '#{gem_name}'"
          log "you can run the sensu-install command again with --verbose for more info" unless options[:verbose]
          log "please take note of any failure messages above"
          log "make sure you have build tools installed (e.g. gcc)"
          log "trying to determine the Sensu plugin homepage for #{gem_name} ..."
          system("gem specification #{gem_name} -r | grep homepage")
          exit 2
        end
      end

      def install_plugins(plugins, options={})
        log "installing Sensu plugins ..."
        log "provided Sensu plugins: #{plugins}" if options[:verbose]
        plugin_gems = plugins.map do |plugin|
          if plugin.start_with?("sensu-plugins-")
            plugin
          else
            "sensu-plugins-#{plugin}"
          end
        end
        log "compiled Sensu plugin gems: #{plugin_gems}" if options[:verbose]
        plugin_gems.reject! do |raw_gem|
          plugin_gem_installed?(raw_gem, options)
        end
        log "Sensu plugin gems to be installed: #{plugin_gems}"
        plugin_gems.each do |raw_gem|
          install_plugin_gem(raw_gem, options)
        end
        log "successfully installed Sensu plugins: #{plugins}"
      end

      def run
        options = cli_options
        unless options[:plugins].empty?
          install_plugins(options[:plugins], options)
        else
          log "nothing to do"
        end
      end
    end
  end
end

Sensu::Install.run
