require 'rhc/rest'

module RHCHelper
  #
  # A class to help maintain the state from rhc calls and helper
  # methods around application management.
  #
  class App
    extend Persistable
    extend Runnable
    extend API
    include API
    include Loggable
    include Commandify
    include Runnable
    include Persistify
    include Httpify

    # attributes to represent the general information of the application
    attr_accessor :name, :type, :hostname, :repo, :embed, :snapshot, :uid, :alias, :scalable, :gear_profile

    # mysql connection information
    attr_accessor :mysql_hostname, :mysql_user, :mysql_password, :mysql_database

    # Create the data structure for a test application
    def initialize(type, name, scalable=false, gear_profile=nil)
      @name, @type, @scalable, @gear_profile = name, type, scalable, gear_profile
      @hostname = "#{name}-#{$namespace}.#{$domain}"
      @repo = "#{TEMP_DIR}/#{$namespace}_#{name}_repo"
      @file = "#{TEMP_DIR}/#{$namespace}.json"
      @embed = []
      @embed_helpers = {}
    end

    def self.rhc_setup
      # Setup questions asked by wizard which are passed in below:
      #   1 - hostname
      #   2 - username
      #   3 - password
      #   4 - should we support an api token, if server supports it
      #   5 - upload SSH keys
      #   5 - if no namespace is found, create namespace? (blank is no)
      args = [ENV['RHC_SERVER']]
      args << $username
      args << $password
      args << 'no' if $supports_auth_tokens
      args << 'yes' unless ($keyed_users ||= []).include?($username)
      args << '' # always skip namespace
      if $namespace
        # Namespace is already created, so don't pass anything in
        logger.info("Namespace (#{$namespace}) should be found by the wizard")
        run("rhc setup", nil, args) do |exitstatus, out, err, arg|
          raise "Unmatched namespace #{$namespace}\n\n#{out}" unless out.include?($namespace)
        end
      else
        # Pass in a blank value for namespace to create in the next step
        args << ''
        logger.info("Skipping namespace creation")
        run("rhc setup", nil, args)
      end
      $keyed_users << $username
    end

    def self.create_unique(type, scalable, gear_profile=nil, prefix="test")
      # Get a REST client to verify the application name
      client = new_client

      # Cleanup all test applications
      test_names = []
      client.domains.each do |domain|
        domain.applications.each do |app|
          test_names << app.name if app.name.start_with?(prefix)
        end
      end

      loop do
        # Generate a random application name
        chars = ("1".."9").to_a
        name = prefix + Array.new(8, '').collect{chars[rand(chars.size)]}.join

        # If the test name exists, try again
        next if test_names.index(name)

        # Create the app
        app = App.new(type, name, scalable, gear_profile)
        app.persist
        return app
      end
    end

    def add_cartridge(name)
      exitcode = 0
      cartridge(name).add do |ec, stdout, stderr, arg|
        exitcode = ec
        embed << name unless embed.include?(name) or ec != 0
      end

      persist
      exitcode
    end

    def remove_cartridge(name)
      cartridge(name).remove
      embed.reject! { |s| s == name }

      persist
    end

    # Get a REST client to verify the application is on the server
    def is_created?
      new_client.find_application($namespace,name)
      true
    rescue RHC::Rest::ApplicationNotFoundException
      false
    end

    def cartridge(name)
      @embed_helpers[name] = RHCHelper::Cartridge.new(self, name) unless @embed_helpers.include?(name)
      @embed_helpers[name]
    end

    def get_index_file
      case @type.split("-").first
        when "php" then "index.php"
        when "ruby" then "config.ru"
        when "python" then "wsgi.py"
        when "perl" then "index.pl"
        when "jbossas" then "src/main/webapp/index.html"
        when "jbosseap" then "src/main/webapp/index.html"
        when "nodejs" then "index.html"
      end
    end

    def get_mysql_file
      case @type.split("-").first
        when "php" then File.expand_path("../misc/php/db_test.php", File.expand_path(File.dirname(__FILE__)))
      end
    end
  end
end
