require 'addressable/uri'

module Rack
  module WebSocket
    module Handler
      class Base
        class Connection < ::EventMachine::WebSocket::Connection

          #########################
          ### EventMachine part ###
          #########################

          # Overwrite new from EventMachine
          # we need to skip standard procedure called
          # when socket is created - this is just a stub
          def self.new(*args)
            instance = allocate
            instance.__send__(:initialize, *args)
            instance
          end

          # Overwrite send_data from EventMachine
          # delegate send_data to rack server
          def send_data(*args)
            EM.next_tick do
              @socket.send_data(*args)
            end
          end

          # Overwrite close_connection from EventMachine
          # delegate close_connection to rack server
          def close_connection(*args)
            EM.next_tick do
              @socket.close_connection(*args)
            end
          end

          #########################
          ### EM-WebSocket part ###
          #########################

          # Overwrite triggers from em-websocket
          def trigger_on_message(msg); @app.on_message(msg); end
          def trigger_on_open; @app.on_open; end
          def trigger_on_close; @app.on_close; end
          def trigger_on_error(error); @app.on_error(error); true; end

          # Overwrite initialize from em-websocket
          # set all standard options and disable
          # EM connection inactivity timeout
          def initialize(app, socket, options = {})
            @app = app
            @socket = socket
            @options = options
            @debug = options[:debug] || false
            @ssl = socket.backend.respond_to?(:ssl?) && socket.backend.ssl?

            socket.websocket = self
            socket.comm_inactivity_timeout = 0

            debug [:initialize]
          end

          # Overwrite dispath from em-websocket
          # we already have request headers parsed so
          # we can skip it and call build_with_request
          def dispatch(data)
            return false if data.nil?
            debug [:inbound_headers, data]
            @handler = EventMachine::WebSocket::HandlerFactory.build_with_request(self, data, data['Body'], @ssl, @debug)
            unless @handler
              # The whole header has not been received yet.
              return false
            end
            @handler.run
            return true
          end

        end
      end
    end
  end
end
