#!/usr/bin/env ruby

require 'rhc/coverage_helper'

require 'rhc-common'

RHC::Helpers.deprecated_command('rhc sshkey',true)

#
# print help
#
def p_usage(exit_code = 255)
  rhlogin = get_var('default_rhlogin') ? "Default: #{get_var('default_rhlogin')}" : "required"
  puts <<USAGE

Usage: #{$0}
Manage multiple keys for the registered rhcloud user.

  rhc-ctl-domain [-l rhlogin] [-p password] [-d] [-h] [-n namespace] (-a key-name [-k ssh-pubkey] | -u key-name [-k ssh-pubkey] | -r key-name | --destroy)

  -l|--rhlogin         rhlogin      OpenShift login (#{rhlogin})
  -p|--password        password     Password (optional, will prompt)
  -n|--namespace       namespace    Namespace for your application(s) (alphanumeric - max #{RHC::DEFAULT_MAX_LENGTH} chars) (required for destroying domain)
  -a|--add-ssh-key     key-name     Add SSH key to the user account (key-name is the user-specified identifier for the key)
  -r|--remove-ssh-key  key-name     Remove SSH key from the user account
  -u|--update-ssh-key  key-name     Update SSH key for the user account
  --destroy                         Destroys the domain and any added ssh keys
  -k|--ssh             key-filepath SSH public key filepath 
  --config             path         Path of alternate config file
  -d|--debug                        Print Debug info
  -h|--help                         Show Usage info

USAGE
exit exit_code
end

begin
    opts = GetoptLong.new(
        ["--debug", "-d", GetoptLong::NO_ARGUMENT],
        ["--help",  "-h", GetoptLong::NO_ARGUMENT],
        ["--rhlogin",  "-l", GetoptLong::REQUIRED_ARGUMENT],
        ["--password",  "-p", GetoptLong::REQUIRED_ARGUMENT],
        ["--namespace",  "-n", GetoptLong::REQUIRED_ARGUMENT],
        ["--add-ssh-key", "-a", GetoptLong::REQUIRED_ARGUMENT],
        ["--remove-ssh-key", "-r", GetoptLong::REQUIRED_ARGUMENT],
        ["--update-ssh-key", "-u", GetoptLong::REQUIRED_ARGUMENT],
        ["--destroy", GetoptLong::NO_ARGUMENT],
        ["--ssh", "-k", GetoptLong::REQUIRED_ARGUMENT],
        ["--config", GetoptLong::REQUIRED_ARGUMENT]
    )
    
    command_list = ['add-ssh-key', 'remove-ssh-key', 'update-ssh-key', 'destroy']
    command_count = 0
    opt = {}
    opts.each do |o, a|
        opt[o[2..-1]] = a.to_s
        
        # check to see if there are multiple commands
        if command_list.include?(o[2..-1])
            command_count += 1
        end
    end
rescue Exception => e
  #puts e.message
  p_usage
end

# If provided a config path, check it
RHC::Config.check_cpath(opt)

# Pull in configs from files
libra_server = get_var('libra_server')
debug = get_var('debug') == 'false' ? nil : get_var('debug')
opt['rhlogin'] = get_var('default_rhlogin') unless opt['rhlogin']

p_usage 0 if opt['help']
p_usage if 0 != ARGV.length

debug = true if opt['debug']

RHC::debug(debug)

# Validate for no command or multiple commands being specified
if command_count == 0
    puts "Missing command! You must specify the operation to perform."
    p_usage
elsif command_count > 1
    puts "Multiple commands specified! You can only perform one operation at a time."
    p_usage
end

if opt['destroy'] && !RHC::check_namespace(opt['namespace'])
    puts "Missing or invalid namespace! You must specify the namespace in order to destroy it."
    p_usage
end


# This is taken care of by the command_count validation performed earlier
#if !opt['rhlogin'] || !(opt['add-key'] || opt['remove-key'] || opt['update-key'] || opt['list-keys']) || \
#   (opt['add-key'] && (opt['remove-key'] || opt['update-key'] || opt['list-keys'])) || \
#   (opt['remove-key'] && (opt['add-key'] || opt['update-key'] || opt['list-keys'])) || \
#   (opt['update-key'] && (opt['add-key'] || opt['remove-key'] || opt['list-keys'])) || \
#   (opt['list-keys'] && (opt['add-key'] || opt['remove-key'] || opt['update-key']))
#    p_usage
#end

if !RHC::check_rhlogin(opt['rhlogin']) || \
   (opt['add-ssh-key'] && !RHC::check_key(opt['add-ssh-key'])) || \
   (opt['remove-ssh-key'] && !RHC::check_key(opt['remove-ssh-key'])) || \
   (opt['update-ssh-key'] && !RHC::check_key(opt['update-ssh-key']))
    p_usage
end

password = opt['password']
if !password
  password = RHC::get_password
end

#
# Read user public ssh key
if opt['add-ssh-key'] || opt['update-ssh-key']
  if opt['ssh']
    if File.readable?(opt['ssh'])
      begin
        ssh_keyfile_contents = File.open(opt['ssh']).gets.chomp.split(' ')
        ssh_key = ssh_keyfile_contents[1]
        ssh_key_type = ssh_keyfile_contents[0]
      rescue Exception => e
        puts "Invalid public keyfile format! Please specify a valid user public keyfile."
        exit 1
      end
    else
      puts "Unable to read user public keyfile #{opt['ssh']}"
      exit 1
    end
  else # create key
    key_name = opt['add-ssh-key'] ? opt['add-ssh-key'] : opt['update-ssh-key']
    puts "Generating ssh key pair for user '#{key_name}' in the dir '#{Dir.pwd}/'"
    # Use system for interaction
    system("ssh-keygen -t rsa -f '#{key_name}'")
    ssh_pub_key_file = Dir.pwd + '/' + key_name + '.pub'
    ssh_keyfile_contents = File.open(ssh_pub_key_file).gets.chomp.split(' ')
    ssh_key = ssh_keyfile_contents[1]
    ssh_key_type = ssh_keyfile_contents[0]
  end
end

data = {}
data[:rhlogin] = opt['rhlogin']
if opt['add-ssh-key']
  url = URI.parse("https://#{libra_server}/broker/ssh_keys")
  data[:key_name] = opt['add-ssh-key']
  data[:ssh] = ssh_key
  data[:action] = 'add-key'
  data[:key_type] = ssh_key_type
elsif opt['remove-ssh-key']
  url = URI.parse("https://#{libra_server}/broker/ssh_keys")
  data[:key_name] = opt['remove-ssh-key']
  data[:action] = 'remove-key'
elsif opt['update-ssh-key']
  url = URI.parse("https://#{libra_server}/broker/ssh_keys")
  data[:key_name] = opt['update-ssh-key']
  data[:ssh] = ssh_key
  data[:action] = 'update-key'
  data[:key_type] = ssh_key_type
elsif opt['destroy']
  url = URI.parse("https://#{libra_server}/broker/domain")
  data[:delete] = true
  data[:namespace] = opt['namespace']
end

RHC::print_post_data(data)
json_data = RHC::generate_json(data)

response = RHC::http_post(RHC::Config.default_proxy, url, json_data, password)

if response.code == '200'
  begin
    json_resp = RHC::json_decode(response.body)
    RHC::update_server_api_v(json_resp)
    RHC::print_response_success(json_resp)
    puts "Success"
    exit 0
  rescue RHC::JsonError
    RHC::print_response_err(response)
  end
else
  RHC::print_response_err(response)
end
puts "Failure"
exit 1
