var uuid = require('node-uuid');

module.exports = function(io, stunservers) {

    var
      activePeople = 0,
      activeRooms = {};

    function describeRoom(name) {
        var clients = io.sockets.clients(name);
        var result = {
            clients: {},
            avatars: {}
        };
        clients.forEach(function (client) {
            result.clients[client.id] = client.resources;
            result.avatars[client.id] = client.avatar;
        });
        return result;
    }

    function safeCb(cb) {
        if (typeof cb === 'function') {
            return cb;
        } else {
            return function () {};
        }
    }

    io.sockets.on('connection', function (client) {
        activePeople += 1;

        client.on('setDetails', function (details) {
            client.profile = {
                username: details.username,
                image: details.image
            };
            client.broadcast.emit('presence', client.profile);
        });

        client.resources = {
            screen: false,
            video: false,
            audio: false
        };

        // pass a message to another id
        client.on('message', function (details) {
            if (!details) return;

            var otherClient = io.sockets.sockets[details.to];
            if (!otherClient) return;

            details.from = client.id;
            otherClient.emit('message', details);
        });

        client.on('shareScreen', function () {
            client.resources.screen = true;
        });

        client.on('unshareScreen', function (type) {
            client.resources.screen = false;
            removeFeed('screen');
        });

        client.on('join', join);
        client.on('videoAdded', videoAdded);

        function videoAdded(data) {
          var socketsInRoom = io.sockets.clients(client.room);
          client.resources.video = true;
          client.avatar = data.avatar;
          socketsInRoom.forEach(function(socket) {
            if (socket.id !== client.id) {
              socket.emit('addVideo', { id: client.id, avatar: data.avatar });
            }
          });
        }

        client.on('requestRoomCount', function(name) {
            client.emit('room_count', {
                room_id: name,
                count: io.sockets.clients(name).length
            });
        });

        client.on('requestActiveRooms', function() {
            client.emit('rooms_count', Object.keys(activeRooms).length);
        });


        function removeFeed(type) {
            if (client.room) {
                io.sockets.in(client.room).emit('remove', {
                    id: client.id,
                    type: type
                });
                if (!type) {
                    client.leave(client.room);
                }
                io.sockets.emit('room_count', {
                    room_id: client.room,
                    count: io.sockets.clients(client.room).length
                });
                if (client.profile) {
                    client.broadcast.emit('vacated_room', {
                        room_id: client.room,
                        profile: client.profile
                    });
                }
                if (io.sockets.clients(client.room).length == 0) {
                    delete activeRooms[client.room];
                    io.sockets.emit('rooms_count', Object.keys(activeRooms).length);
                }
                if (!type) {
                    client.room = undefined;
                }
            }
        }

        function join(name, cb) {
            // sanity check
            if (typeof name !== 'string') return;
            // leave any existing rooms
            removeFeed();
            safeCb(cb)(null, describeRoom(name));
            client.join(name);
            io.sockets.emit('room_count', {
                room_id: name,
                count: io.sockets.clients(name).length
            });
            if (client.profile) {
                client.broadcast.emit('presence_room', {
                    room_id: name,
                    profile: client.profile
                });
            }
            io.sockets.clients(name).forEach(function (s) {
                if (s.profile) {
                    client.emit('presence_room', {
                        room_id: name,
                        profile: s.profile
                    });
                }
            });
            client.room = name;
            activeRooms[name] = true;
            io.sockets.emit('rooms_count', Object.keys(activeRooms).length);
        }

        // we don't want to pass "leave" directly because the
        // event type string of "socket end" gets passed too.
        client.on('disconnect', function () {
            removeFeed();
            activePeople -= 1;
            io.sockets.emit('users_count', activePeople);
            if (client.profile) {
                io.sockets.emit('vacated', client.profile);
            }
        });
        client.on('leave', function () {
            removeFeed();
        });

        client.on('create', function (name, cb) {
            if (arguments.length == 2) {
                cb = (typeof cb == 'function') ? cb : function () {};
                name = name || uuid();
            } else {
                cb = name;
                name = uuid();
            }
            // check if exists
            if (io.sockets.clients(name).length) {
                safeCb(cb)('taken');
            } else {
                join(name);
                safeCb(cb)(null, name);
            }
        });

        // tell client about stun and turn servers and generate nonces
        client.emit('stunservers', stunservers || []);

        client.emit('rooms_count', Object.keys(activeRooms).length);
        io.sockets.emit('users_count', activePeople);
        io.sockets.clients().forEach(function (socket) {
            if (socket.id !== client.id && socket.profile) client.emit('presence', socket.profile);
        });
    });
};