 class IDEAppController extends AppController
+
+  _.extend @prototype, CollaborationController.prototype
 
   {
     Stopped, Running, NotInitialized, Terminated, Unknown, Pending,

      delete @modal


  handleBroadcastMessage: (data) ->

    {origin, type} = data

    if origin is KD.nick()
      switch type
        when 'ParticipantWantsToLeave'
          return @quit()
        when 'ParticipantKicked'
          return @handleParticipantKicked data.target
        else return

    switch type

      when 'SessionEnded'

        @showSessionEndedModal()

      when 'ParticipantWantsToLeave'

        @handleParticipantKicked data.origin

      when 'ParticipantKicked'

        return  unless data.origin is @collaborationHost

        if data.target is KD.nick()
          @removeMachineNode()
          @showKickedModal()
        else
          @handleParticipantKicked data.target


  unshareMachineAndKlient: (username, fetchUser = no) ->

    if fetchUser
      return KD.remote.cacheable username, (err, accounts) =>

        return KD.showError err  if err

        @setMachineUser accounts, no


    @listChatParticipants (accounts) =>

      for account in accounts when account.profile.nickname is username
        target = account

      @setMachineUser [target], no  if target


  showKickedModal: ->
    options        =
      title        : 'Your session has been closed'
      content      : "You have been removed from the session by @#{@collaborationHost}."
      blocking     : yes
      buttons      :
        ok         :
          title    : 'OK'
          callback : => @modal.destroy()

    @showModal options
    @quit()


  quit: ->

    KD.utils.killRepeat @autoSaveInterval
    KD.utils.killRepeat @pingInterval
    @rtm?.dispose()
    @rtm = null

    KD.singletons.router.handleRoute '/IDE'
    KD.singletons.appManager.quit this


  showSessionEndedModal: (content) ->

    content ?= "This session is ended by @#{@collaborationHost} You won't be able to access it anymore."

    options        =
      title        : 'Session ended'
      content      : content
      blocking     : yes
      buttons      :
        quit       :
          title    : 'LEAVE'
          callback : => @modal.destroy()

    @showModal options
    @removeMachineNode()
    @quit()


  handleParticipantLeaveAction: ->

    options   =
      title   : 'Are you sure?'
      content : "If you leave this session you won't be able to return back."

    @showModal options, =>
      @broadcastMessages.push origin: KD.nick(), type: 'ParticipantWantsToLeave'
      @stopChatSession()
      @modal.destroy()

      options = channelId: @socialChannel.getId()
      KD.singletons.socialapi.channel.leave options, (err) =>
        return KD.showError err  if err
        @setMachineUser [KD.whoami()], no, => @quit()
        # remove the leaving participant's info from the collaborative doc
        @removeParticipant KD.nick()


  removeMachineNode: ->

    KD.singletons.mainView.activitySidebar.removeMachineNode @mountedMachine


  handleParticipantKicked: (username) ->

    @chat.emit 'ParticipantLeft', username
    @statusBar.removeParticipantAvatar username
    @removeParticipantCursorWidget username
    # remove participant's all data persisted in realtime appInfo
    @removeParticipant username

  getCollaborationData: (callback = noop) =>

    collaborationData =
      watchMap        : @myWatchMap?.values()
      amIHost         : @amIHost

    callback collaborationData


  kickParticipant: (account) ->

    return  unless @amIHost

    options      =
      channelId  : @socialChannel.id
      accountIds : [ account.socialApiId ]

    @setMachineUser [account], no, =>

      KD.singletons.socialapi.channel.kickParticipants options, (err, result) =>

        return KD.showError err  if err

        targetUser = account.profile.nickname
        message    =
          type     : 'ParticipantKicked'
          origin   : KD.nick()
          target   : targetUser

        @broadcastMessages.push message
        @handleParticipantKicked targetUser


  getCollaborationHost: -> if @amIHost then KD.nick() else @collaborationHost


  isHostOnline: ->

    host = @getCollaborationHost()

    filtered = @participants
      .asArray()
      .filter (its) -> its.nickname is host

    return no  unless filtered.length

    { sessionId } = filtered.first

    return no  unless sessionId

    final = @rtm
      .getCollaborators()
      .filter (its) -> its.sessionId is sessionId

    return final.length > 0


  listenPings: ->

    pingInterval = 1000 * 5
    pongInterval = 1000 * 15

    @pingInterval = if @amIHost
    then KD.utils.repeat pingInterval, @bound 'sendPing'
    else KD.utils.repeat pongInterval, @bound 'checkPing'


  sendPing: -> @pingTime.setText Date.now().toString()


  forceQuitCollaboration: ->

    { Collaboration } = KD.remote.api
    Collaboration.stop @rtmFileId, @workspaceData, (err) =>

      return warn err  if err

      KD.utils.killRepeat @pingInterval

      @stopCollaborationSession =>
        @quit()

        new KDNotificationView
          title    : "@#{@collaborationHost} has left the session."
          duration : 3000


  checkPing: do ->

    lastCheckedAt = null
    lastPing      = null
    errorTryCount = 3
    diffInterval  = KD.config.collaboration.timeout

    return ->

      ping = @pingTime.getText()

      # kill session if `errorTryCount`
      # limit is passed.
      if errorTryCount <= 0
        @forceQuitCollaboration()
      # update the lastChecked at if the last ping
      # is still the same, decrease the error try count.
      else if ping is lastPing and errorTryCount > 0
        errorTryCount -= 1
        lastCheckedAt = Date.now()
        return
      # this is the happy path.
      else if lastPing - ping < diffInterval
        lastCheckedAt = Date.now()
        lastPing      = ping
        errorTryCount = 3
        return


  removeParticipantCursorWidget: (targetUser) ->

        @mySnapshot.set paneHash, change


  showModal: (modalOptions = {}, callback = noop) ->
    return  if @modal

