# encoding: utf-8

module WatirSpec
  class Server < Sinatra::Base
    class << self
      attr_accessor :autorun

      def run_async
        case WatirSpec.platform
        when :java
          Thread.new { run! }
          sleep 0.1 until WatirSpec::Server.running?
        when :windows
          run_in_child_process
        else
          pid = fork { run! }
          sleep 0.5 until listening?
        end

        if pid
          # is this really necessary?
          at_exit {
            begin
              Process.kill 0, pid
              alive = true
            rescue Errno::ESRCH
              alive = false
            end

            Process.kill(9, pid) if alive
          }
        end
      end

      def run!
        handler = detect_rack_handler
        handler.run(self, :Host => bind, :Port => port) { @running = true }
      end

      def listening?
        $stderr.puts "trying #{bind}:#{port}..."

        TCPSocket.new(bind, port).close
        true
      rescue
        false
      end

      def find_free_port_above(int)
        port = int

        until free_port?(port)
          port += 1
        end

        port
      end

      def autorun
        @autorun ||= true
      end

      def should_run?
        autorun && !running?
      end

      def running?
        defined?(@running) && @running
      end

      def free_port?(port)
        s = TCPServer.new(@host, port)
        s.close
        true
      rescue SocketError, Errno::EADDRINUSE
        false
      end

      private

      def run_in_child_process
        begin
          require "childprocess"
        rescue LoadError => ex
          raise "please run `gem install childprocess` for WatirSpec on Windows + MRI\n\t(caught: #{ex.message})"
        end

        process = ChildProcess.build(WatirSpec.ruby, File.expand_path("../../spec_helper", __FILE__))
        at_exit { process.stop }
      end
    end # class << Server

    set :public,      WatirSpec.html
    set :static,      true
    set :run,         false
    set :environment, :production
    set :bind,        "localhost" if WatirSpec.platform == :windows
    set :port,        find_free_port_above(2000)
    set :server,      %w[mongrel webrick]

    get '/' do
      self.class.name
    end

    class BigContent
      def each(&blk)
        yield "<html><head><title>Big Content</title></head><body>"

        string = "hello"*205

        300.times do
          yield string
        end

        yield "</body></html>"
      end
    end

    get '/big' do
      BigContent.new
    end

    post '/post_to_me' do
      "You posted the following content:\n#{ env['rack.input'].read }"
    end

    get '/plain_text' do
      content_type 'text/plain'
      'This is text/plain'
    end

    get '/ajax' do
      sleep 10
      "A slooow ajax response"
    end

    get '/charset_mismatch' do
      content_type 'text/html; charset=UTF-8'
      %{
        <html>
          <head>
            <meta http-equiv="Content-type" content="text/html; charset=iso-8859-1" />
          </head>
          <body>
            <h1>ΓΈ</h1>
          </body>
        </html>
      }
    end

    get '/octet_stream' do
      content_type 'application/octet-stream'
      'This is application/octet-stream'
    end

    get '/set_cookie' do
      content_type 'text/plain'
      headers 'Set-Cookie' => "monster=/"

      "C is for cookie, it's good enough for me"
    end

    get '/header_echo' do
      content_type 'text/plain'
      env.inspect
    end

    get '/authentication' do
      auth = Rack::Auth::Basic::Request.new(env)

      unless auth.provided? && auth.credentials == %w[foo bar]
        headers 'WWW-Authenticate' => %(Basic realm="localhost")
        halt 401, 'Authorization Required'
      end

      "ok"
    end

    get '/encodable_<stuff>' do
      'page with characters in URI that need encoding'
    end

  end # Server
end # WatirSpec