<commit_before>/// <reference path="../../../../node_modules/@types/node/index.d.ts" />
import { Injectable } from '@angular/core'
import { BehaviorSubject, ReplaySubject, Observable, Observer } from 'rxjs/Rx'
import * as netflux from 'netflux'

import { JoinEvent } from './JoinEvent'
import { NetworkMessage } from './NetworkMessage'
import { BotStorageService } from 'core/bot-storage/bot-storage.service'
import { environment } from '../../../environments/environment'
const pb = require('./message_pb.js')


@Injectable()
export class NetworkService {

  private botStorageService: BotStorageService

  private key: string
  private webChannel
  private doorOwnerId: number // One of the peer id

  private joinObservable: Observable<JoinEvent>
  private joinObserver: Observer<JoinEvent>
  private leaveSubject: BehaviorSubject<number>
  private messageSubject: ReplaySubject<NetworkMessage>
  private peerJoinSubject: ReplaySubject<number>
  private peerLeaveSubject: ReplaySubject<number>
  private peerSelectionSubject: BehaviorSubject<number>
  private doorSubject: BehaviorSubject<boolean>
  private docTitleSubject: BehaviorSubject<string>

  constructor (botStorageService: BotStorageService) {
    this.botStorageService = botStorageService
    this.doorOwnerId = null
    this.messageSubject = new ReplaySubject<NetworkMessage>()
    this.joinObservable = Observable.create((observer) => {
      this.joinObserver = observer
    })
    this.leaveSubject = new BehaviorSubject<number>(-1)
    this.peerJoinSubject = new ReplaySubject<number>()
    this.peerLeaveSubject = new ReplaySubject<number>()
    this.doorSubject = new BehaviorSubject<boolean>(true)
    this.docTitleSubject = new BehaviorSubject<string>('Untitled document')

    this.initWebChannel()
  }

  initWebChannel () {
    this.webChannel = netflux.create({signalingURL: environment.signalingURL})

    // Leave webChannel before closing tab or browser
    window.addEventListener('beforeunload', (event) => this.webChannel.leave())

    // Peer JOIN event
    this.webChannel.onPeerJoin = (id) => {
      if (this.doorOwnerId === this.webChannel.myId) {
        this.sendDoor(true, true, null, id)
      }
      this.peerJoinSubject.next(id)
    }

    // Peer LEAVE event
    this.webChannel.onPeerLeave = (id) => {
      if (this.doorOwnerId === id) {
        this.setDoor(false)
      }
      this.peerLeaveSubject.next(id)
    }

    // On door closed
    this.webChannel.onClose = () => this.setDoor(false)

    // Message event
    this.webChannel.onMessage = (id, bytes, isBroadcast) => {
      let msg = pb.Message.deserializeBinary(bytes)
      switch (msg.getTypeCase()) {
        case pb.Message.TypeCase.MSG:
          let newMsg = msg.getMsg()
          this.messageSubject.next(new NetworkMessage(newMsg.getService(), id, isBroadcast, newMsg.getContent()))
          break
        case pb.Message.TypeCase.DOOR:
          let door = msg.getDoor()
          if (door.getMustclose() !== null && door.getMustclose()) {
            this.openDoor(false)
          } else {
            if (!door.getOpened()) {
              if (!door.getIntentionally()) {
                // Reopen door or not
              } else {
                  this.setDoor(false)
              }
            } else {
              this.setDoor(true, id)
            }
          }
          break
        case pb.Message.TypeCase.DOC:
          log.debug('Doc title received: ' + msg.getDoc().getTitle())
          this.docTitleSubject.next(msg.getDoc().getTitle())
          break
        case pb.Message.TypeCase.TYPE_NOT_SET:
          log.error('network', 'Protobuf: message type not set')
          break
      }
    }
  }

  newSend (service: string, content: ArrayBuffer, id?: number) {
    let msg = new pb.Message()
    let newmsg = new pb.Newmessage()
    newmsg.setService(service)
    newmsg.setContent(content)
    msg.setMsg(newmsg)
    if (id) {
      this.webChannel.sendTo(id, msg.serializeBinary())
    } else {
      this.webChannel.send(msg.serializeBinary())
    }
  }

  getDoor (): number {
    return this.doorOwnerId
  }

  setDoor (opened: boolean, id: number | null = null): void {
    this.doorOwnerId = id
    this.doorSubject.next(opened)
  }

  openDoor (open: boolean) {
    if (open) {
      // Opening door only if it closed
      if (!this.webChannel.isOpen()) {
        this.webChannel.open({key: this.key})
          .then((openData) => {
            log.info('network', `Opened a door with the signaling: ${this.webChannel.settings.signalingURL}`)
            this.setDoor(true, this.webChannel.myId)
            this.sendDoor(true, true, null)
          })
          .catch((reason) => {
            log.warn('Could not open a door with the signaling: '
              + `${this.webChannel.settings.signalingURL}: ${reason}`, this.webChannel)
          })
      }
    } else {
      // Closing door
      if (this.doorOwnerId !== null) {
        if (this.doorOwnerId === this.webChannel.myId) {
          log.debug('I\'m closing door')
          this.webChannel.close()
          this.sendDoor(false, true, null)
        } else {
          this.sendDoor(null, null, true, this.doorOwnerId)
        }
      }
    }
  }

  get myId (): number {<commit_msg>fix(network): Fix default value of doorOwnerId<commit_after>/// <reference path="../../../../node_modules/@types/node/index.d.ts" />
import { Injectable } from '@angular/core'
import { BehaviorSubject, ReplaySubject, Observable, Observer } from 'rxjs/Rx'
import * as netflux from 'netflux'

import { JoinEvent } from './JoinEvent'
import { NetworkMessage } from './NetworkMessage'
import { BotStorageService } from 'core/bot-storage/bot-storage.service'
import { environment } from '../../../environments/environment'
const pb = require('./message_pb.js')


@Injectable()
export class NetworkService {

  private botStorageService: BotStorageService

  private key: string
  private webChannel
  private doorOwnerId: number // One of the peer id

  private joinObservable: Observable<JoinEvent>
  private joinObserver: Observer<JoinEvent>
  private leaveSubject: BehaviorSubject<number>
  private messageSubject: ReplaySubject<NetworkMessage>
  private peerJoinSubject: ReplaySubject<number>
  private peerLeaveSubject: ReplaySubject<number>
  private peerSelectionSubject: BehaviorSubject<number>
  private doorSubject: BehaviorSubject<boolean>
  private docTitleSubject: BehaviorSubject<string>

  constructor (botStorageService: BotStorageService) {
    this.botStorageService = botStorageService
    this.doorOwnerId = -1
    this.messageSubject = new ReplaySubject<NetworkMessage>()
    this.joinObservable = Observable.create((observer) => {
      this.joinObserver = observer
    })
    this.leaveSubject = new BehaviorSubject<number>(-1)
    this.peerJoinSubject = new ReplaySubject<number>()
    this.peerLeaveSubject = new ReplaySubject<number>()
    this.doorSubject = new BehaviorSubject<boolean>(true)
    this.docTitleSubject = new BehaviorSubject<string>('Untitled document')

    this.initWebChannel()
  }

  initWebChannel () {
    this.webChannel = netflux.create({signalingURL: environment.signalingURL})

    // Leave webChannel before closing tab or browser
    window.addEventListener('beforeunload', (event) => this.webChannel.leave())

    // Peer JOIN event
    this.webChannel.onPeerJoin = (id) => {
      if (this.doorOwnerId === this.webChannel.myId) {
        this.sendDoor(true, true, null, id)
      }
      this.peerJoinSubject.next(id)
    }

    // Peer LEAVE event
    this.webChannel.onPeerLeave = (id) => {
      if (this.doorOwnerId === id) {
        this.setDoor(false)
      }
      this.peerLeaveSubject.next(id)
    }

    // On door closed
    this.webChannel.onClose = () => this.setDoor(false)

    // Message event
    this.webChannel.onMessage = (id, bytes, isBroadcast) => {
      let msg = pb.Message.deserializeBinary(bytes)
      switch (msg.getTypeCase()) {
        case pb.Message.TypeCase.MSG:
          let newMsg = msg.getMsg()
          this.messageSubject.next(new NetworkMessage(newMsg.getService(), id, isBroadcast, newMsg.getContent()))
          break
        case pb.Message.TypeCase.DOOR:
          let door = msg.getDoor()
          if (door.getMustclose() !== null && door.getMustclose()) {
            this.openDoor(false)
          } else {
            if (!door.getOpened()) {
              if (!door.getIntentionally()) {
                // Reopen door or not
              } else {
                  this.setDoor(false)
              }
            } else {
              this.setDoor(true, id)
            }
          }
          break
        case pb.Message.TypeCase.DOC:
          log.debug('Doc title received: ' + msg.getDoc().getTitle())
          this.docTitleSubject.next(msg.getDoc().getTitle())
          break
        case pb.Message.TypeCase.TYPE_NOT_SET:
          log.error('network', 'Protobuf: message type not set')
          break
      }
    }
  }

  newSend (service: string, content: ArrayBuffer, id?: number) {
    let msg = new pb.Message()
    let newmsg = new pb.Newmessage()
    newmsg.setService(service)
    newmsg.setContent(content)
    msg.setMsg(newmsg)
    if (id) {
      this.webChannel.sendTo(id, msg.serializeBinary())
    } else {
      this.webChannel.send(msg.serializeBinary())
    }
  }

  getDoor (): number {
    return this.doorOwnerId
  }

  setDoor (opened: boolean, id: number = -1): void {
    this.doorOwnerId = id
    this.doorSubject.next(opened)
  }

  openDoor (open: boolean) {
    if (open) {
      // Opening door only if it closed
      if (!this.webChannel.isOpen()) {
        this.webChannel.open({key: this.key})
          .then((openData) => {
            log.info('network', `Opened a door with the signaling: ${this.webChannel.settings.signalingURL}`)
            this.setDoor(true, this.webChannel.myId)
            this.sendDoor(true, true, null)
          })
          .catch((reason) => {
            log.warn('Could not open a door with the signaling: '
              + `${this.webChannel.settings.signalingURL}: ${reason}`, this.webChannel)
          })
      }
    } else {
      // Closing door
      if (this.doorOwnerId !== -1) {
        if (this.doorOwnerId === this.webChannel.myId) {
          log.debug('I\'m closing door')
          this.webChannel.close()
          this.sendDoor(false, true, null)
        } else {
          this.sendDoor(null, null, true, this.doorOwnerId)
        }
      }
    }
  }

  get myId (): number {
{'fraction_non_alphanumeric': 0.12326817232871512, 'fraction_numerical': 0.00047447333459859557, 'mean_word_length': 2.595701125895599, 'pattern_counts': {'":': 0, '<': 35, '<?xml version=': 0, '>': 51, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2350858', 'n_tokens_mistral': 3142, 'n_tokens_neox': 3079, 'n_words': 656}