/***/
var http = require('http'), https = require('https');
var events = require('events'), util = require('util');

var Socket = require('./socket');

module.exports = WebSocketServer;

var evts = ['request', 'connection', 'close', 'checkContinue', 'upgrade',
  'clientError'];
var fncs = ['listen', 'close'];

function WebSocketServer(options) {
  var self = this;
  events.EventEmitter.call(self);

  var server, opts = 'object' === typeof options ? options: {};

  if('server' in opts)
    server = opts['server'], delete opts['server'];

  else {
    var prtcl = 'key' in opts && 'cert' in opts ? https: http;
    server = prtcl.createServer.apply(prtcl, arguments);
  }

  evts.forEach(function(evt) {
    _bubble(evt, server, self);
  });

  fncs.forEach(function(fnc) {
    _wrap(fnc, server, self);
  });

  var connections = {};

  self.on('upgrade', function(req, socket, upgradeHead) {
    var conn = new Socket(req, socket, upgradeHead, opts);
    var _socket = conn._socket = socket.soket || socket;
    var site = req.url, port = _socket.remotePort;

    conn._req = req;

    conn.on('open', function() {
      var internal = connections[site] = connections[site] || [];
      // conn['_id'] = port;
      internal.push(conn);
      // TODO check delete ok
      /*
      self.emit('connect', conn);
      self.emit('handShake', conn);
      */
    });

    conn.on('close', function() {
      var internal = connections[site] || [];
      var index = internal.indexOf(conn);
      0 <= index && internal.splice(index, 1);

      self.emit('release');
    });

    conn.on('broadcast', function(message, options) {
      options = options || {};
      if(options.conn)
        options.conn = conn;
      if(options.site)
        options.site = site;
      self.emit('broadcast', message, options);
    });

    self.emit('connect', conn);
    self.emit('handShake', conn);

  });

  self.on('broadcast', function(message, options) {
    var type = options.type, conn = options.conn, site = options.site;
    var broadfn = conn ? distribute: broadcast;
    if(site)
      broadfn(connections[site]);
    else
      for( var i in connections)
        broadfn(connections[i]);
    function broadcast(cons) {
      for( var i in cons)
        cons[i].send(message, type);
    }
    function distribute(cons) {
      for( var i in cons) {
        if(cons[i] == conn)
          continue;
        cons[i].send(message, type);
      }
    }
  });
}
util.inherits(WebSocketServer, events.EventEmitter);

WebSocketServer.prototype.broadcast = function(message, options) {
  this.emit('broadcast', message, options || '');
};

function _bubble(evt, from, to) {
  from.on(evt, function() {
    var args = Array.prototype.slice.call(arguments);
    args.unshift(evt);
    events.EventEmitter.prototype.emit.apply(to, args);
  });
}

function _wrap(fnc, from, to) {
  to[fnc] = function() {
    return from[fnc].apply(from, arguments);
  };
}

@@ -2065,21 +2065,127 @@
 st;%0A
+%0A
     if(
+!
 site)%0A
+      for( var i in connections)%0A        broadfn(connections%5Bi%5D);%0A%0A    else if(typeof site == 'string')%0A
     
@@ -2214,24 +2214,25 @@
 site%5D);%0A
+%0A
     else
 %0A      f
@@ -2223,16 +2223,51 @@
     else
+ if(typeof site.test == 'function')
 %0A      f
@@ -2291,32 +2291,48 @@
 ections)%0A       
+ site.test(i) &&
  broadfn(connect
@@ -2340,16 +2340,77 @@
 ons%5Bi%5D);
+%0A%0A    else%0A      throw new Error('unexpected site: ' + site);
 %0A    fun

improve limited cast pattern