#
#   Functions to help determine the status of a Tomcat web server
#
module ControllerLaunchpad
  
  #
  # Get the status of a launchpad server.
  #
  # Returns:
  #     down - can't even contact the server with a socket call
  #     up - contacted server with socket call and http call
  #     responded - the server responded to http, but not success
  #     error - who knows, maybe a network error or something
  #
  #  NOTE: this function requires the launchpad to contain a file
  #           named tooltwist/images/poweredByTooltwist-small.png.
  #
  def self.status(port)
    showUri = false
    
    # Try calling the server over a socket first (it's faster than HTTP?)
    begin # exception block
      s = TCPSocket.open("localhost", port)
      s.close               # Close the socket when done
      #print "Socket opened ok\n"
    rescue
      #print "Could not open socket: #{$!}\n"
      return "down"
    end # exception block
    
    # Now try an HTTP request
    begin #exception block
      uri_string = "http://localhost:#{port}/ttsvr/tooltwist/images/poweredByTooltwist-small.png"
      if showUri
        print "testing using=#{uri_string}\n"
        showUri = false # only show it once
      end
      uri = URI(uri_string)
      Net::HTTP.start(uri.host, uri.port) do |http|
        request = Net::HTTP::Get.new uri.request_uri
        response = http.request request
        
        #print "http request returned #{response.code}\n"
        return "responded - #{response.message}" if not response.is_a?(Net::HTTPOK)
        return "up"
      end
    rescue
      print "Error with http request: #{$!}\n"
      return "error - #{$!}"
    end #exception block

  end #self.status
  
  #
  #   Wait for a launchpad to start.
  #
  def self.wait_to_start(port)
    
    # Loop around until we get a successful call to the server
    # - give up after a while
    # - if we get a  socket success and HTTP error, and a subsequent socket failure, then
    #   we can assume the server had a fatal error and shut back down.
    timeout = 60 # how many seconds to keep trying until we give up.
    sleep_time = 3
    beginning = Time.now
    previous_socket_success = false
    while true
      
      status = ControllerLaunchpad::status(port)
      print "==>> Status is #{status}\n"
      
      # decide what to do with the reply
      if status == "up"
        # yeah! socket and http succeeded
        return true
      elsif status == "down"
        # socket failed
        if previous_socket_success
          return false
        end
      else
        # socket succeeded, but HTTP failed
        previous_socket_success = true
      end # status
  
      # code block
      elapsed_time = Time.now - beginning
      #print "Time elapsed #{elapsed_time} seconds\n"
      if elapsed_time > timeout
        print "Server has not started after #{timeout} seconds.\n"
        return false
      end
      
      # pause for a while before trying again
      sleep sleep_time
    end # while

  end # self.wait_to_start
  
  #
  #   Start the launchpad server if it is not already running
  #
  #   Prerequisites:
  #     call ControllerMisc.setupGlobals() before calling this function
  #
  def self.startup_if_not_running(port)
    
    # Check the current status
    status = status(port)
    #print "status is #{status}\n"
    
    # if the status is indeterminate, perhaps the server is shutting down
    if status != "up" and status != "down"
      print "Indeterminate server state - waiting 5 seconds...\n"
      sleep 5
      status = status(port)
      print "status: #{status}\n"
    end
    
    # if the server is not down, then it is either up, or coming up
    if status != "down"
      print "Launchpad is already running.\n"
      return
    end

    # Set the Java environment variables
    java_opts = "-Xms512m -Xmx5g -XX:MaxPermSize=512m"
    print "Setting JAVA_OPTS=#{java_opts}\n"
    ENV["JAVA_OPTS"] = java_opts

    
    # Start the server
    tomcatBinDir = "#{$IMAGE_DIR}/tomcat/bin"
    Dir.chdir(tomcatBinDir) do
      if RUBY_PLATFORM.downcase.include?("mswin")
        # Running on Windows
        cmd = "./startup.bat"
      else
        # *nix
        cmd = "./startup.sh"
      end
      print "\nStarting the launchpad...\n"
      print  "$ #{cmd}\n"
      system cmd
      print "\nWait a bit...\n"
      sleep 5
    end
  end
  
  #
  #   Shutdown the launchpad server if it is running
  #
  #   Prerequisites:
  #     call ControllerMisc.setupGlobals() before calling this function
  #
  def self.shutdown_if_running(port)
    
    # Check the current status
    status = status(port)
    if status == "down"
      print "Launchpad is not running.\n"
      return
    end
    
    # Shutdown the server (if we have the command to do it)
    tomcatBinDir = "#{$IMAGE_DIR}/tomcat/bin"
    if File.exists?(tomcatBinDir)
      Dir.chdir(tomcatBinDir) do
        if RUBY_PLATFORM.downcase.include?("mswin")
          # Running on Windows
          cmd = "shutdown.bat"
        else
          # *nix
          cmd = "./shutdown.sh"
        end
        print "\nShutting down the launchpad...\n"
        print  "$ #{cmd}\n"
        system cmd
        print "\nWait a bit...\n"
        sleep 5
      end
    end
  end
  
end
