/*
The MIT License

Copyright (c) 2012, Mozilla Foundation
Copyright (c) 2012, Alan Kligman
All rights reserved.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

(function() {

  /* Notes
   *
   * - Continue using prefixed names for now.
   *
   */

  var io = SocketIO;
  var webrtcSupported = true;

  var RTCPeerConnection;
  if(window.mozRTCPeerConnection)
    RTCPeerConnection = window.mozRTCPeerConnection;
  else if(window.webkitRTCPeerConnection)
    RTCPeerConnection = window.webkitRTCPeerConnection;
  else if(window.RTCPeerConnection)
    RTCPeerConnection = window.RTCPeerConnection
  else
    webrtcSupported = false;

  var RTCSessionDescription;
  if(window.mozRTCSessionDescription)
    RTCSessionDescription = window.mozRTCSessionDescription;
  else if(window.webkitRTCSessionDescription)
    RTCSessionDescription = window.webkitRTCSessionDescription;
  else if(window.RTCSessionDescription)
    RTCSessionDescription = window.RTCSessionDescription
  else
    webrtcSupported = false;

  var RTCIceCandidate;
  if(window.mozRTCIceCandidate)
    RTCIceCandidate = window.mozRTCIceCandidate;
  else if(window.webkitRTCIceCandidate)
    RTCIceCandidate = window.webkitRTCIceCandidate;
  else if(window.RTCIceCandidate)
    RTCIceCandidate = window.RTCIceCandidate;
  else
    webrtcSupported = false;

  var getUserMedia;
  if(!navigator.getUserMedia) {
    if(navigator.mozGetUserMedia)
      getUserMedia = navigator.mozGetUserMedia.bind(navigator);
    else if(navigator.webkitGetUserMedia)
      getUserMedia = navigator.webkitGetUserMedia.bind(navigator);
    else
      webrtcSupported = false;
  } else {
    getUserMedia = navigator.getUserMedia.bind(navigator);
  }

  // FIXME: browser detection is gross, but I don't see another way to do this
  var RTCConnectProtocol;
  if(window.mozRTCPeerConnection) {
    RTCConnectProtocol = mozRTCConnectProtocol;
  } else if(window.webkitRTCPeerConnection) {
    RTCConnectProtocol = webkitRTCConnectProtocol;
  } else {
    webrtcSupported = false;
  }

  function callback(object, method, args) {
    if(!Array.isArray(args))
      args = [args];
    if(method in object && 'function' === typeof object[method]) {
      object[method].apply(object, args);
    }
  };

  function fail(object, method, error) {
    if (!(error instanceof Error))
      error = new Error(error);
    callback(object, method, [error]);
  };

  function defer(queue, object, method, args) {
    if(queue) {
      queue.push([object, method, args]);
      return true;
    } else {
      return false;
    }
  };

  function processDeferredQueue(queue) {
    while(queue.length) {
      var deferred = queue.shift();
      callback(deferred[0], deferred[1], deferred[2]);
    }
  };

  var ONE_SECOND = 1000; // milliseconds
  var DEFAULT_CONNECTION_TIMEOUT = 10 * ONE_SECOND;
  var DEFAULT_PING_TIMEOUT = 1 * ONE_SECOND;
  var RELIABLE_CHANNEL_OPTIONS = {
    reliable: false
  };
  var UNRELIABLE_CHANNEL_OPTIONS = {
    outOfOrderAllowed: true,
    maxRetransmitNum: 0,
    reliable: false
  };

  function PendingConnectionAbortError(message) {
    this.name = "PendingConnectionAbortError";
    this.message = (message || "");
  };
  PendingConnectionAbortError.prototype = Error.prototype;

  function ConnectionFailedError(message) {
    this.name = "ConnectionFailedError";
    this.message = (message || "");
  };
  ConnectionFailedError.prototype = Error.prototype;

  var E = {
    PendingConnectionAbortError: PendingConnectionAbortError,
    ConnectionFailedError: ConnectionFailedError
  };

  function WebSocketBroker(brokerUrl) {
    this.brokerUrl = brokerUrl;
    this.state = WebSocketBroker.OFFLINE;

    this.onstatechange = null;
    this.onreceive = null;
    this.onerror = null;

    this.socket = null;
    this.route = null;
  };

  // States
  WebSocketBroker.OFFLINE     = 0x00;
  WebSocketBroker.CONNECTING  = 0x01;
  WebSocketBroker.CONNECTED   = 0x02;
  // Flags
  WebSocketBroker.ROUTED      = 0x10;
  WebSocketBroker.LISTENING   = 0x20;

  WebSocketBroker.prototype.setState = function setState(state, clearFlags) {
    var clear = clearFlags ? 0x00 : 0xF0;
    this.state &= clear >>> 0;
    this.state |= state >>> 0;
    callback(this, 'onstatechange', [this.state, (state | (clear & 0x0)) >>> 0]);
  };
  WebSocketBroker.prototype.setFlag = function setFlag(flag) {
    this.state = (this.state | flag) >>> 0;
    callback(this, 'onstatechange', [this.state, flag])
  };
  WebSocketBroker.prototype.clearFlag = function clearFlag(flag) {
    flag = (~flag) >>> 0;
    this.state = (this.state & flag) >>> 0;
    callback(this, 'onstatechange', [this.state, flag])
  };
  WebSocketBroker.prototype.checkState = function checkState(mask) {
    return !!(this.state & mask);
  };
  WebSocketBroker.prototype.connect = function connect() {
    var that = this;
    var socket = io.connect(this.brokerUrl + '/peer', {
      'sync disconnect on unload': true // partially fixes 'interrupted while page loading' warning
    });

    socket.on('connecting', function onconnecting() {
      that.setState(WebSocketBroker.CONNECTING, true);
    });

    socket.on('connect', function onconnect() {
      that.setState(WebSocketBroker.CONNECTED, true);
    });

    socket.on('connect_failed', function onconnect_failed() {
      that.setState(WebSocketBroker.OFFLINE, true);
    });

    socket.on('route', function onroute(route) {
      that.route = route;
      that.setFlag(WebSocketBroker.ROUTED);
    });

    socket.on('disconnect', function ondisconnect() {
      that.setState(WebSocketBroker.OFFLINE, true);
    });

    socket.on('error', function onerror(error) {
      fail(that, 'onerror', error);
    });

    socket.on('receive', function onreceive(message) {
      var from = message['from'];
      var data = message['data'];
      callback(that, 'onreceive', [from, data]);
    });

    this.socket = socket;
  };
  WebSocketBroker.prototype.disconnect = function disconnect() {
    if(this.checkState(WebSocketBroker.CONNECTED)) {
      this.socket.disconnect();
      this.setState(WebSocketBroker.OFFLINE, true);
      return true;
    } else {
      return false;
    }
  };
  WebSocketBroker.prototype.listen = function listen(options) {
    var that = this;
    if(this.checkState(WebSocketBroker.CONNECTED)) {
      this.socket.emit('listen', options, function onresponse(response) {
        if(response && response['error']) {
          var error = new Error(response['error']);
          fail(that, 'onerror', error);
        } else {
          that.setFlag(WebSocketBroker.LISTENING);
        }
      });
    }
  };
  WebSocketBroker.prototype.ignore = function ignore() {
    var that = this;
    if(this.checkState(WebSocketBroker.CONNECTED)) {
      this.socket.emit('ignore', null, function onresponse(response) {
        if(response && response['error']) {
          var error = new Error(response['error']);
          fail(that, 'onerror', error)
        } else {
          that.clearFlag(WebSocketBroker.LISTENING);
        }
      });
    }
  };
  WebSocketBroker.prototype.send = function send(to, message) {
    var that = this;
    if(this.checkState(WebSocketBroker.CONNECTED)) {
      this.socket.emit('send', {'to': to, 'data': message}, function onresponse(response) {
        if(response && response['error']) {
          var error = new Error(response['error']);
          fail(that, 'onerror', error)
        }
      });
    };
  };

  var dataChannels = {
    'reliable': 'RELIABLE',
    'unreliable': 'UNRELIABLE',
    '@control': 'RELIABLE'
  };
  var nextDataConnectionPort = 1;
  function CommonRTCConnectProtocol() {
    // FIXME: these timeouts should be configurable
    this.connectionTimeout = 10 * ONE_SECOND;
    this.pingTimeout = 1 * ONE_SECOND;
  };
  CommonRTCConnectProtocol.prototype.process = function process(message) {
    var that = this;

    var type = message['type'];
    switch(type) {
      case 'ice':
        var candidate = JSON.parse(message['candidate']);
        if(candidate)
          this.handleIce(candidate);
        break;

      case 'offer':
        that.ports.remote = message['port'];
        var offer = {
          'type': 'offer',
          'sdp': message['description']
        };
        this.handleOffer(offer);
        break;

      case 'answer':
        that.ports.remote = message['port'];
        var answer = {
          'type': 'answer',
          'sdp': message['description']
        };
        this.handleAnswer(answer);
        break;

      case 'abort':
        this.handleAbort();
        break;

      default:
        fail(this, 'onerror', 'unknown message');
    }
  };
  CommonRTCConnectProtocol.prototype.handleAbort = function handleAbort() {
    fail(this, 'onerror', new Error(E.RTCConnectProtocolAbort));
  };
  CommonRTCConnectProtocol.prototype.initialize = function initialize(cb) {
    var that = this;

    if(this.peerConnection)
      return cb();

    // FIXME: peer connection servers should be configurable
    this.peerConnection = new RTCPeerConnection(this.connectionServers, this.connectionOptions);
    this.peerConnection.onicecandidate = function(event) {
      var message = {
        'type': 'ice',
        'candidate': JSON.stringify(event.candidate)
      };
      callback(that, 'onmessage', message);
    };
    this.peerConnection.onaddstream = function(event) {
      that.streams['remote'] = event.stream;
    };
    this.peerConnection.onstatechange = function(event) {
      console.log(event.target.readyState);
    };

    function createStream(useFake) {
      useFake = (!useVideo && !useAudio) ? true : useFake;
      var useVideo = !!that.options['video'];
      var useAudio = !!that.options['audio'];
      var mediaOptions = {
        video: useVideo,
        audio: (!useVideo && !useAudio) ? true : useAudio,
        fake: useFake
      };
      getUserMedia(mediaOptions,
        function(stream) {
          that.peerConnection.addStream(stream);
          that.streams['local'] = stream;
          cb();
        },
        function(error) {
          console.error('!', error);
          if(!useFake)
            createStream(true);
          else
            fail(that, 'onerror', error);
        }
      );
    }

    createStream();
  };
  CommonRTCConnectProtocol.prototype.handleIce = function handleIce(candidate) {
    var that = this;

    function setIce() {
      if(!that.peerConnection.remoteDescription) {
        return
      }
      that.peerConnection.addIceCandidate(new RTCIceCandidate(candidate),
        function() {},
        function(error) {
          fail(that, 'onerror', error);
        }
      );
    };

    this.initialize(setIce);
  };
  CommonRTCConnectProtocol.prototype.initiate = function initiate() {
    var that = this;
    this.initiator = true;

    function createDataChannels() {
      var labels = Object.keys(dataChannels);
      labels.forEach(function(label) {
        var channelOptions = that.channelOptions[dataChannels[label]];
        var channel = that._pending[label] = that.peerConnection.createDataChannel(label, channelOptions);
        channel.binaryType = that.options['binaryType'];
        channel.onopen = function() {
          that.channels[label] = channel;
          delete that._pending[label];
          if(Object.keys(that.channels).length === labels.length) {
            that.complete = true;
            callback(that, 'oncomplete', []);
          }
        };
        channel.onerror = function(error) {
          console.error(error);
          fail(that, 'onerror', error);
        };
      });
      createOffer();
    };

    function createOffer() {
      that.peerConnection.createOffer(setLocal,
        function(error) {
          fail(that, 'onerror', error);
        }
      );
    };

    function setLocal(description) {
      that.peerConnection.setLocalDescription(new RTCSessionDescription(description), complete,
        function(error) {
          fail(that, 'onerror', error);
        }
      );

      function complete() {
        var message = {
          'type': 'offer',
          'description': description['sdp'],
          'port': that.ports.local
        };
        callback(that, 'onmessage', message);
      };
    };

    this.initialize(createDataChannels);
  };
  CommonRTCConnectProtocol.prototype.handleOffer = function handleOffer(offer) {
    var that = this;

    function handleDataChannels() {
      var labels = Object.keys(dataChannels);
      that.peerConnection.ondatachannel = function(event) {
        var channel = event.channel;
        var label = channel.label;
        that._pending[label] = channel;
        channel.binaryType = that.options['binaryType'];
        channel.onopen = function() {
          that.channels[label] = channel;
          delete that._pending[label];
          if(Object.keys(that.channels).length === labels.length) {
            that.complete = true;
            callback(that, 'oncomplete', []);
          }
        };
        channel.onerror = function(error) {
          console.error(error);
          fail(that, 'onerror', error);
        };
      };
      setRemote();
    };

    function setRemote() {
      that.peerConnection.setRemoteDescription(new RTCSessionDescription(offer), createAnswer,
        function(error) {
          fail(that, 'onerror', error);
        }
      );
    };

    function createAnswer() {
      that.peerConnection.createAnswer(setLocal,
        function(error) {
          fail(that, 'onerror', error);
        }
      );
    };

    function setLocal(description) {
      that.peerConnection.setLocalDescription(new RTCSessionDescription(description), complete,
        function(error) {
          fail(that, 'onerror', error);
        }
      );

      function complete() {
        var message = {
          'type': 'answer',
          'description': description['sdp'],
          'port': that.ports.local
        };
        callback(that, 'onmessage', message);
      };
    };

    this.initialize(handleDataChannels);
  };
  CommonRTCConnectProtocol.prototype.handleAnswer = function handleAnswer(answer) {
    var that = this;

    function setRemote() {
      that.peerConnection.setRemoteDescription(new RTCSessionDescription(answer), complete,
        function(error) {
          fail(that, 'onerror', error);
        }
      );
    };

    function complete() {
    };

    this.initialize(setRemote);
  };

  function mozRTCConnectProtocol(options) {
    this.options = options;
    this.onmessage = null;
    this.oncomplete = null;
    this.onerror = null;

    this.complete = false;
    this.ports = {
      local: nextDataConnectionPort ++,
      remote: null
    };
    this.streams = {
      local: null,
      remote: null
    };
    this.initiator = false;

    this.peerConnection = null;
    this.channels = {};
    this._pending = {};
    this.connectionServers = null;
    this.connectionOptions = null;
    this.channelOptions = {
      RELIABLE: {
        // defaults
      },
      UNRELIABLE: {
        outOfOrderAllowed: true,
        maxRetransmitNum: 0
      }
    };
  };
  mozRTCConnectProtocol.prototype = new CommonRTCConnectProtocol();
  mozRTCConnectProtocol.prototype.constructor = mozRTCConnectProtocol;

  function webkitRTCConnectProtocol(options) {
    this.options = options;
    this.onmessage = null;
    this.oncomplete = null;
    this.onerror = null;

    this.complete = false;
    this.ports = {
      local: nextDataConnectionPort ++,
      remote: null
    };
    this.streams = {
      local: null,
      remote: null
    };
    this.initiator = false;

    this.peerConnection = null;
    this.channels = {};
    this._pending = {};
    this.connectionServers = {iceServers:[{url:'stun:23.21.150.121'}]};
    this.connectionOptions = {
      'optional': [{ 'RtpDataChannels': true }]
    };
    this.channelOptions = {
      RELIABLE: {
        // FIXME: reliable channels do not work in chrome yet
        reliable: false
      },
      UNRELIABLE: {
        reliable: false
      }
    };
  };
  webkitRTCConnectProtocol.prototype = new CommonRTCConnectProtocol();
  webkitRTCConnectProtocol.prototype.constructor = webkitRTCConnectProtocol;

  // FIXME: this could use a cleanup
  var nextConnectionId = 1;
  function Connection(options, peerConnection, streams, channels) {
    var that = this;
    this.id = nextConnectionId ++;
    this.streams = streams;
    this.connected = false;
    this.messageFlag = false;

    this.onmessage = null;
    this.ondisconnect = null;
    this.onerror = null;

    this.peerConnection = peerConnection;

    // DataChannels
    this.channels = channels;

    this.connectionTimer = null;
    this.pingTimer = null;

    function handleConnectionTimerExpired() {
      if(!that.connected)
        return
      this.connectionTimer = null;
      if(false === that.messageFlag) {
        that.channels['@control'].send('ping');
        this.pingTimer = window.setTimeout(handlePingTimerExpired, options['pingTimeout']);
      } else {
        that.messageFlag = false;
        this.connectionTimer = window.setTimeout(handleConnectionTimerExpired, options['connectionTimeout']);
      }
    };
    function handlePingTimerExpired() {
      if(!that.connected)
        return
      this.pingTimer = null;
      if(false === that.messageFlag) {
        that.connected = false;
        that.close();
      } else {
        that.messageFlag = false;
        this.connectionTimer = window.setTimeout(handleConnectionTimerExpired, options['connectionTimeout']);
      }
    };

    Object.keys(this.channels).forEach(function(label) {
      var channel = that.channels[label];
      if(label.match('^@')) // check for internal channels
        return;

      channel.onmessage = function onmessage(message) {
        that.messageFlag = true;
        callback(that, 'onmessage', [label, message]);
      };
    });
    this.channels['@control'].onmessage = function onmessage(message) {
      that.messageFlag = true;
      if(that.connected) {
        var data = message.data;
        if('ping' === data) {
          that.channels['@control'].send('pong');
        } else if('pong' === data) {
          // ok
        } else if('quit' === data) {
          that.close();
        }
      }
    };

    this.connected = true;
    this.connectionTimer = window.setTimeout(handleConnectionTimerExpired, options['connectionTimeout']);
  };
  Connection.prototype.close = function close() {
    console.log('close connection');
    if(this.connected) {
      this.channels['@control'].send('quit');
    }
    this.connected = false;
    this.peerConnection.close();
    if(this.connectionTimer) {
      window.clearInterval(this.connectionTimer);
      this.connectionTimer = null;
    }
    if(this.pingTimer) {
      window.clearInterval(this.pingTimer);
      this.pingTimer = null;
    }
    this.peerConnection = null;
    callback(this, 'ondisconnect', []);
  };
  Connection.prototype.send = function send(label, message) {
    this.channels[label].send(message);
  };

  function PendingConnection(route, incoming) {
    this.route = route;
    this.incoming = incoming;
    this.proceed = true;
  };
  PendingConnection.prototype.accept = function accept() {
    this.proceed = true;
  };
  PendingConnection.prototype.reject = function reject() {
    this.proceed = false;
  };

  function Peer(brokerUrl, options) {
    if(!webrtcSupported)
      throw new Error("WebRTC not supported");

    var that = this;
    this.brokerUrl = brokerUrl;
    this.options = options = options || {};
    options['binaryType'] = options['binaryType'] || 'arraybuffer';
    options['connectionTimeout'] = options['connectionTimeout'] || 10 * ONE_SECOND;
    options['pingTimeout'] = options['pingTimeout'] || 1 * ONE_SECOND;

    this.onconnection = null;
    this.onpending = null;
    this.onroute = null;
    this.onerror = null;

    this.broker = new WebSocketBroker(brokerUrl);
    this.pending = {};

    this.queues = {
      connected: [],
      listening: []
    };

    this.broker.onstatechange = function onstatechange(state, mask) {
      if(that.queues.connected.length && that.broker.checkState(WebSocketBroker.ROUTED)) {
        processDeferredQueue(that.queues.connected);
        if(that.queues.listening.length && that.broker.checkState(WebSocketBroker.LISTENING)) {
          processDeferredQueue(that.queues.listening);
        }
      }
      if(mask & WebSocketBroker.ROUTED) {
        callback(that, 'onroute', that.broker.route);
      }
    };

    this.broker.onreceive = function onreceive(from, message) {
      var handshake;
      if(!that.pending.hasOwnProperty(from)) {
        if(!that.broker.checkState(WebSocketBroker.LISTENING)) {
          return;
        }

        var pendingConnection = new PendingConnection(from, /*incoming*/ true);
        callback(that, 'onpending', [pendingConnection]);
        if(!pendingConnection['proceed'])
          return;

        var handshake = that.pending[from] = new RTCConnectProtocol(that.options);
        handshake.oncomplete = function() {
          var connection = new Connection(that.options, handshake.peerConnection, handshake.streams, handshake.channels);
          connection['route'] = from;
          delete that.pending[from];
          callback(that, 'onconnection', [connection]);
        };
        handshake.onmessage = function(message) {
          that.broker.send(from, message);
        };
        handshake.onerror = function(error) {
          delete that.pending[from];
          callback(that, 'onerror', [error]);
        };
      } else {
        handshake = that.pending[from];
      }
      handshake.process(message);
    };

    this.broker.connect();
  };
  Peer.prototype.listen = function listen(options) {
    if(!this.broker.checkState(WebSocketBroker.ROUTED))
      return defer(this.queues.connected, this, 'listen', [options]);

    options = options || {};
    options['url'] = options['url'] || window.location.toString();
    options['listed'] = (undefined !== options['listed']) ? options['listed'] : true;
    options['metadata'] = options['metadata'] || {};

    this.broker.listen(options);
  };
  Peer.prototype.ignore = function ignore() {
    throw new Error('not implemented');
  };
  Peer.prototype.connect = function connect(route) {
    if(!this.broker.checkState(WebSocketBroker.ROUTED))
      return defer(this.queues.connected, this, 'connect', [route]);

    var that = this;

    if(this.pending.hasOwnProperty(route))
      throw new Error('already connecting to this host'); // FIXME: we can handle this better

    var pendingConnection = new PendingConnection(route, /*incoming*/ false);
    callback(that, 'onpending', [pendingConnection]);
    if(!pendingConnection['proceed'])
      return;

    var handshake = this.pending[route] = new RTCConnectProtocol(this.options);
    handshake.oncomplete = function() {
      var connection = new Connection(this.options, handshake.peerConnection, handshake.streams, handshake.channels);
      connection['route'] = route;
      delete that.pending[route];
      callback(that, 'onconnection', [connection]);
    };
    handshake.onmessage = function(message) {
      that.broker.send(route, message);
    };
    handshake.onerror = function(error) {
      delete that.pending[route];
      fail(that, 'onerror', error);
    };

    handshake.initiate();
  };
  Peer.prototype.close = function close() {
    this.broker.disconnect();
  };
  Peer.E = E;

  return Peer;

})();