'use strict';

var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');

var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);

var _createClass2 = require('babel-runtime/helpers/createClass');

var _createClass3 = _interopRequireDefault(_createClass2);

var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');

var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);

var _inherits2 = require('babel-runtime/helpers/inherits');

var _inherits3 = _interopRequireDefault(_inherits2);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

/**
 * Created by godsong on 16/6/24.
 */
var Emitter = require('events').EventEmitter;
var uuid = require('../util/uuid');

var Peer = function (_Emitter) {
    (0, _inherits3.default)(Peer, _Emitter);

    function Peer(websocket) {
        (0, _classCallCheck3.default)(this, Peer);

        var _this = (0, _possibleConstructorReturn3.default)(this, Object.getPrototypeOf(Peer).call(this));

        _this.messageBuffer = [];
        _this.websocket = websocket;
        _this.websocket.on('close', function () {
            console.log('socket close');
            if (_this.oppositePeer) {
                _this.oppositePeer.oppositePeer = null;
            }
            _this.oppositePeer = null;
            _this.websocket = null;
            if (_this.messageBuffer.length > 0) {
                console.warn('loss message');
            }
            _this.messageBuffer = [];
            _this.emit('close');
        });
        return _this;
    }

    (0, _createClass3.default)(Peer, [{
        key: 'send',
        value: function send(message) {
            var _this2 = this;

            if (Array.isArray(message)) {
                message.forEach(function (m) {
                    _this2.websocket.send(JSON.stringify(m));
                });
            } else {
                this.websocket.send(JSON.stringify(message));
            }
        }
    }, {
        key: 'setOppositePeer',
        value: function setOppositePeer(peer) {
            this.oppositePeer = peer;
            if (this.messageBuffer.length > 0) {
                peer.send(this.messageBuffer);
                this.messageBuffer = [];
            }
        }
    }]);
    return Peer;
}(Emitter);

var _sessionMap = {};

var P2PSession = function (_Emitter2) {
    (0, _inherits3.default)(P2PSession, _Emitter2);

    function P2PSession() {
        (0, _classCallCheck3.default)(this, P2PSession);

        var _this3 = (0, _possibleConstructorReturn3.default)(this, Object.getPrototypeOf(P2PSession).call(this));

        _this3.peerList = [];
        _this3.id = uuid();
        _this3.emptyCount = 0;
        _this3.maxTimeoutCount = 10;
        return _this3;
    }

    (0, _createClass3.default)(P2PSession, [{
        key: 'join',
        value: function join(websocket) {
            this.addPeer(websocket);
        }
    }, {
        key: 'setTimeout',
        value: function setTimeout(timeout) {
            this.maxTimeoutCount = timeout;
        }
    }, {
        key: 'destroy',
        value: function destroy() {
            this.removeAllListeners();
            this.peerList = null;
            clearInterval(this.idleTimer);
            this.isTimeout = false;
        }
    }, {
        key: 'postMessage',
        value: function postMessage(websocket, message) {
            var peer = this.findPeer(websocket);
            if (peer.oppositePeer) {
                peer.oppositePeer.send(message);
            } else {
                peer.messageBuffer.push(message);
            }
        }
    }, {
        key: 'findPeer',
        value: function findPeer(websocket) {
            return this.peerList.filter(function (peer) {
                return peer.websocket === websocket;
            })[0];
        }
    }, {
        key: 'addPeer',
        value: function addPeer(websocket) {
            var _this4 = this;

            var peer = new Peer(websocket);
            if (this.peerList.length == 0) {
                this.peerList.push(peer);
            } else if (this.peerList.length == 1) {
                peer.setOppositePeer(this.peerList[0]);
                this.peerList.push(peer);
                this.peerList[0].setOppositePeer(peer);
            } else {
                this.peerList.forEach(function (peer) {
                    return console.log('state:', peer.websocket.readyState);
                });
                console.log('Peer session can not add the third peer!');
                return;
            }
            peer.on('close', function () {
                var l = _this4.peerList.length;
                _this4.peerList = _this4.peerList.filter(function (p) {
                    return p !== peer;
                });
                if (_this4.peerList.length == 0) {
                    _this4.idleTimer = setInterval(function () {
                        _this4.emptyCount++;
                        if (_this4.emptyCount >= _this4.maxTimeoutCount) {
                            _this4.isTimeout = true;
                            _this4.emit('timeout');
                        }
                    }, 2000);
                }
            });
            clearInterval(this.idleTimer);
            this.emptyCount = 0;
            this.isTimeout = false;
        }
    }], [{
        key: 'newSession',
        value: function newSession(websocket) {
            var session = new P2PSession();
            session.addPeer(websocket);
            websocket._p2pSessionId = session.id;
            _sessionMap[session.id] = session;
            return session;
        }
    }, {
        key: 'postMessage',
        value: function postMessage(websocket, message) {
            var peer = _sessionMap[websocket._p2pSessionId].findPeer(websocket);
            if (peer.oppositePeer) {
                peer.oppositePeer.send(message);
            } else {
                peer.messageBuffer.push(message);
            }
        }
    }, {
        key: 'join',
        value: function join(sessionId, websocket) {
            if (_sessionMap[sessionId]) {
                websocket._p2pSessionId = sessionId;
                _sessionMap[sessionId].addPeer(websocket);
                return true;
            } else {
                return false;
            }
        }
    }]);
    return P2PSession;
}(Emitter);

module.exports = P2PSession;