#!/usr/bin/env ruby
# Copyright 2011 Red Hat, Inc.
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

require 'rhc-common'

def p_usage
    libra_server = get_var('libra_server')
    rhlogin = get_var('default_rhlogin') ? "Default: #{get_var('default_rhlogin')}" : "required"
    type_keys = RHC::get_cartridge_listing(nil, ', ', libra_server, @http, 'standalone', false)
    puts <<USAGE

Usage: #{$0}
Create an OpenShift Express app.

  -a|--app   application     Application name  (alphanumeric - max #{RHC::APP_NAME_MAX_LENGTH} chars) (required)
  -t|--type  type            Type of app to create (#{type_keys}) (required)
  -l|--rhlogin  rhlogin      Red Hat login (RHN or OpenShift login with OpenShift Express access) (#{rhlogin})
  -p|--password  password    RHLogin password  (optional, will prompt)
  -r|--repo  path            Git Repo path (defaults to ./$app_name)
  -n|--nogit                 Only create remote space, don't pull it locally
  -d|--debug                 Print Debug info
  -h|--help                  Show Usage info
  --no-dns                   Skip DNS check. Must be used in combination with --nogit
  --config  path             Path of alternate config file
  --timeout #                Timeout, in seconds, for connection
  --enable-jenkins [name]    Indicates to create a Jenkins application (if not already available)
                             and embed the Jenkins client into this application.  The default 
                             name will be 'jenkins' if not specified. Note that --no-dns is ignored
                             for the creation of the Jenkins application.

USAGE
exit 255
end

begin
    opts = GetoptLong.new(
        ["--debug", "-d", GetoptLong::NO_ARGUMENT],
        ["--help",  "-h", GetoptLong::NO_ARGUMENT],
        ["--no-dns", GetoptLong::NO_ARGUMENT],
        ["--nogit", "-n", GetoptLong::NO_ARGUMENT],
        ["--rhlogin",  "-l", GetoptLong::REQUIRED_ARGUMENT],
        ["--password",  "-p", GetoptLong::REQUIRED_ARGUMENT],
        ["--app",   "-a", GetoptLong::REQUIRED_ARGUMENT],
        ["--repo",  "-r", GetoptLong::REQUIRED_ARGUMENT],
        ["--config", GetoptLong::REQUIRED_ARGUMENT],
        ["--type",  "-t", GetoptLong::REQUIRED_ARGUMENT],
        ["--timeout", GetoptLong::REQUIRED_ARGUMENT],
        ["--enable-jenkins", GetoptLong::OPTIONAL_ARGUMENT]
    )
    opt = {}
    opts.each do |o, a|
        opt[o[2..-1]] = a.to_s
    end
rescue Exception => e
  #puts e.message
    p_usage
end

# If provided a config path, check it
check_cpath(opt)

# Pull in configs from files
libra_server = get_var('libra_server')
debug = get_var('debug') == 'false' ? nil : get_var('debug')

if opt["help"]
    p_usage
end

if opt["debug"]
    debug = true
end
RHC::debug(debug)

RHC::timeout(opt['timeout'] ? opt['timeout'] : get_var('timeout'))

opt['rhlogin'] = get_var('default_rhlogin') unless opt['rhlogin']

if !RHC::check_rhlogin(opt['rhlogin'])
    p_usage
end

if !RHC::check_app(opt['app'])
    p_usage
end

if !opt['type']
    puts 'Type is required'
    p_usage
end

if !opt['rhlogin'] || !opt['app'] || !opt['type']
    p_usage
end

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

user_info = RHC::get_user_info(libra_server, opt['rhlogin'], password, @http, false)
app_info = user_info['app_info']

if app_info[opt['app']]
  puts "An application named '#{opt['app']}' in namespace '#{user_info['user_info']['namespace']}' already exists"
  exit 255
end

jenkins_app_name = nil
has_jenkins = false
if opt['enable-jenkins']
  app_info.each do |app_name, app|
    if app['framework'] == 'jenkins-1.4'
      jenkins_app_name = app_name
      has_jenkins = true
      puts "
Found existing Jenkins application: #{jenkins_app_name}
"
      if !opt['enable-jenkins'].empty?
        puts "Ignoring specified Jenkins app name: #{opt['enable-jenkins']}"
      end
    end
  end
  if !has_jenkins
    if opt['type'] =~ /^jenkins-/
      has_jenkins = true
      if opt['no-dns']
        puts "
The --no-dns option can't be used in conjunction with --enable-jenkins 
when creating a #{opt['type']} application.  Either remove the --no-dns
option or first install your #{opt['type']} application with --no-dns
and then use rhc-ctl-app to embed the Jenkins client. 
"
        exit 255
      end
      jenkins_app_name = opt['app']
      puts "
The Jenkins client will be embedded into the Jenkins application 
currently being created: '#{opt['app']}'
"
    end
  end
  if !has_jenkins
    if !opt['enable-jenkins'].empty?
      jenkins_app_name = opt['enable-jenkins']
    else
      jenkins_app_name = 'jenkins'
    end
  
    if !RHC::check_app(jenkins_app_name)
        p_usage
    end

    if jenkins_app_name == opt['app']
      puts "You must specify a different name for your application and Jenkins ('#{opt['app']}')."
      exit 100
    end
  
    if app_info.has_key?(jenkins_app_name)
      puts "You already have an application named '#{jenkins_app_name}'."
      puts "In order to continue you'll need to specify a different name"
      puts "with --enable-jenkins or destroy the existing application."
      exit 100
    end
  end
end

opt['repo'] = opt['app'] unless opt['repo']

if @mydebug
  puts "
  Found a bug? Post to the forum and we'll get right on it.
      IRC: #openshift on freenode
      Forums: https://www.redhat.com/openshift/forums
  
  "
end

#
# Confirm local git repo exists
#
unless opt['nogit']
    if File.exists?(opt['repo'])
        puts "We will not overwrite an existing git repo. Please remove:"
        puts "  #{File.expand_path(opt['repo'])}"
        puts "Then try again."
        puts
        exit 210
    else
        begin
            # Create the parent directory for the git repo
            @git_parent = File.expand_path(opt['repo'] + "/../")
            FileUtils.mkdir_p(@git_parent)
        rescue Exception => e
            puts "Could not write to #{@git_parent}"
            puts "Reason: #{e.message}"
            puts
            puts "Please re-run from a directory you have write access to or specify -r with a"
            puts "path you have write access to"
            puts
            exit 211
        end
    end
end

if jenkins_app_name && !has_jenkins
  jenkins_app = RHC::create_app(libra_server, @http, user_info, jenkins_app_name, 'jenkins-1.4', opt['rhlogin'], password, nil, false, true, true)
  available = RHC::check_app_available(@http, jenkins_app[:app_name], jenkins_app[:fqdn], jenkins_app[:health_check_path], jenkins_app[:result], jenkins_app[:git_url], nil, true)
  if !available
    puts "Unable to access your new Jenkins application."
    exit 1
  end
end

#
# Create remote application space
#
main_app = RHC::create_app(libra_server, @http, user_info, opt['app'], opt['type'], opt['rhlogin'], password, opt['repo'], opt['no-dns'], opt['nogit'], false)
if jenkins_app_name
  puts "Now embedding the jenkins client into '#{opt['app']}'..."
  RHC::ctl_app(libra_server, @http, opt['app'], opt['rhlogin'], password, 'configure', true, 'jenkins-client-1.4', nil, false)
end

unless opt['no-dns']
  available = RHC::check_app_available(@http, main_app[:app_name], main_app[:fqdn], main_app[:health_check_path], main_app[:result], main_app[:git_url], opt['repo'], opt['nogit'])
  if !available
    puts "Unable to access your new application."
    exit 1
  end
end