/* eslint-disable
    camelcase,
    n/handle-callback-err,
    max-len,
    no-return-assign,
*/
// TODO: This file was created by bulk-decaffeinate.
// Fix any style issues and re-enable lint.
/*
 * decaffeinate suggestions:
 * DS101: Remove unnecessary use of Array.from
 * DS102: Remove unnecessary code created because of implicit returns
 * DS206: Consider reworking classes to avoid initClass
 * DS207: Consider shorter variations of null checks
 * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
 */
import ColorManager from '../colors/ColorManager'
import 'crypto-js/md5'

let OnlineUsersManager

export default OnlineUsersManager = (function () {
  OnlineUsersManager = class OnlineUsersManager {
    static initClass() {
      this.prototype.cursorUpdateInterval = 500
    }

    constructor(ide, $scope) {
      this.ide = ide
      this.$scope = $scope
      this.$scope.onlineUsers = {}
      this.$scope.onlineUserCursorHighlights = {}
      this.$scope.onlineUsersArray = []
      this.$scope.onlineUsersCount = 0

      this.$scope.$on('cursor:editor:update', (event, position) => {
        return this.sendCursorPositionUpdate(position)
      })

      this.$scope.$on('project:joined', () => {
        return this.ide.socket.emit(
          'clientTracking.getConnectedUsers',
          (error, connectedUsers) => {
            this.$scope.onlineUsers = {}
            for (const user of Array.from(connectedUsers || [])) {
              if (user.client_id === this.ide.socket.publicId) {
                // Don't store myself
                continue
              }
              // Store data in the same format returned by clientTracking.clientUpdated

              this.$scope.onlineUsers[user.client_id] = {
                id: user.client_id,
                user_id: user.user_id,
                email: user.email,
                name: `${user.first_name} ${user.last_name}`,
                doc_id:
                  user.cursorData != null ? user.cursorData.doc_id : undefined,
                row: user.cursorData != null ? user.cursorData.row : undefined,
                column:
                  user.cursorData != null ? user.cursorData.column : undefined,
              }
            }
            return this.refreshOnlineUsers()
          }
        )
      })

      this.ide.socket.on('clientTracking.clientUpdated', client => {
        if (client.id !== this.ide.socket.publicId) {
          // Check it's not me!
          return this.$scope.$apply(() => {
            this.$scope.onlineUsers[client.id] = client
            return this.refreshOnlineUsers()
          })
        }
      })

      this.ide.socket.on('clientTracking.clientDisconnected', client_id => {
        return this.$scope.$apply(() => {
          delete this.$scope.onlineUsers[client_id]
          return this.refreshOnlineUsers()
        })
      })

      this.$scope.getHueForUserId = user_id => {
        return ColorManager.getHueForUserId(user_id)
      }
    }

    refreshOnlineUsers() {
      this.$scope.onlineUsersArray = []

      for (const client_id in this.$scope.onlineUsers) {
        const user = this.$scope.onlineUsers[client_id]
        if (user.doc_id != null) {
          user.doc = this.ide.fileTreeManager.findEntityById(user.doc_id)
        }

        // If the user's name is empty use their email as display name
        // Otherwise they're probably an anonymous user
        if (user.name === null || user.name.trim().length === 0) {
          if (user.email) {
            user.name = user.email.trim()
          } else if (user.user_id === 'anonymous-user') {
            user.name = 'Anonymous'
          }
        }

        user.initial = user.name != null ? user.name[0] : undefined
        if (!user.initial || user.initial === ' ') {
          user.initial = '?'
        }

        this.$scope.onlineUsersArray.push(user)
      }

      // keep a count of the other online users
      this.$scope.onlineUsersCount = this.$scope.onlineUsersArray.length

      this.$scope.onlineUserCursorHighlights = {}
      for (const client_id in this.$scope.onlineUsers) {
        const client = this.$scope.onlineUsers[client_id]
        const { doc_id } = client
        if (doc_id == null || client.row == null || client.column == null) {
          continue
        }
        if (!this.$scope.onlineUserCursorHighlights[doc_id]) {
          this.$scope.onlineUserCursorHighlights[doc_id] = []
        }
        this.$scope.onlineUserCursorHighlights[doc_id].push({
          label: client.name,
          cursor: {
            row: client.row,
            column: client.column,
          },
          hue: ColorManager.getHueForUserId(client.user_id),
        })
      }

      if (this.$scope.onlineUsersArray.length > 0) {
        delete this.cursorUpdateTimeout
        return (this.cursorUpdateInterval = 500)
      } else {
        delete this.cursorUpdateTimeout
        return (this.cursorUpdateInterval = 60 * 1000 * 5)
      }
    }

    sendCursorPositionUpdate(position) {
      if (position != null) {
        this.$scope.currentPosition = position // keep track of the latest position
      }
      if (this.cursorUpdateTimeout == null) {
        return (this.cursorUpdateTimeout = setTimeout(() => {
          const doc_id = this.$scope.editor.open_doc_id
          // always send the latest position to other clients
          this.ide.socket.emit('clientTracking.updatePosition', {
            row:
              this.$scope.currentPosition != null
                ? this.$scope.currentPosition.row
                : undefined,
            column:
              this.$scope.currentPosition != null
                ? this.$scope.currentPosition.column
                : undefined,
            doc_id,
          })

          return delete this.cursorUpdateTimeout
        }, this.cursorUpdateInterval))
      }
    }
  }
  OnlineUsersManager.initClass()
  return OnlineUsersManager
})()
