
import autobind from 'autobind-decorator'
import BaseSvc from './BaseSvc'
import io from 'socket.io'

export default class SocketSvc extends BaseSvc {

  /////////////////////////////////////////////////////////////////
  //
  //
  /////////////////////////////////////////////////////////////////
  constructor (config) {

    super (config)

    this._connections = {}

    this._io = io(config.server)

    this._io.sockets.on(
      'connection',
      this.handleConnection)
  }

  /////////////////////////////////////////////////////////////////
  //
  //
  /////////////////////////////////////////////////////////////////
  name() {

    return 'SocketSvc'
  }

  ///////////////////////////////////////////////////////////////////
  // Socket Connection handler
  //
  ///////////////////////////////////////////////////////////////////
  @autobind
  handleConnection (socket) {

    var _thisSvc = this

    _thisSvc._connections[socket.id] = socket

    socket.on('request.connection.data', ()=> {
      socket.emit('connection.data', {
        socketId: socket.id
      })
    })

    socket.on('disconnect', ()=> {

      _thisSvc.handleDisconnection(socket.id)
    })

    socket.on('broadcast', (data) => {

      let socketIds = Object.keys(_thisSvc._connections)

      let filter = socketIds.filter((socketId) => {
        return socketId !== socket.id
      })

      _thisSvc.broadcast(data.msgId, data.msg, filter)
    })

    _thisSvc.emit('SocketSvc.Connection', {
      id: socket.id
    })

    console.log('Socket connected: ' + socket.id)
  }

  ///////////////////////////////////////////////////////////////////
  // Socket Disconnection handler
  //
  ///////////////////////////////////////////////////////////////////
  @autobind
  handleDisconnection (id) {

    var _thisSvc = this

    _thisSvc.emit('SocketSvc.Disconnection', {
      id: id
    })

    if(_thisSvc._connections[id]){

      delete _thisSvc._connections[id]

      console.log('Socket disconnected: ' + id)
    }
  }

  ///////////////////////////////////////////////////////////////////
  // filter: array of socketIds to broadcast
  // If null, broadcast to every connected socket
  //
  ///////////////////////////////////////////////////////////////////
  broadcast (msgId, msg, filter = null) {

    var _thisSvc = this

    if (filter) {

      filter = Array.isArray(filter) ? filter : [filter]

      filter.forEach((socketId) => {

        if(_thisSvc._connections[socketId]){

          var socket = _thisSvc._connections[socketId]

          socket.emit(msgId, msg)
        }
      })

    } else {

      for(var socketId in _thisSvc._connections){

        var socket = _thisSvc._connections[socketId]

        socket.emit(msgId, msg)
      }
    }
  }
}
