import 'rxjs/add/observable/merge' ; import 'rxjs/add/operator/switchMap' ; import { Injectable } from '@angular/core' ; import { AuthService } from '../auth/auth.service' ; import { AngularFirestore , AngularFirestoreCollection , AngularFirestoreDocument } from 'angularfire2/firestore' ; import { Moderator , RoomMessages , Message , Room , User , RoomUsers , SuspendedUsers } from './data.model' ; import { Observable } from 'rxjs/Observable' ; import { BehaviorSubject } from 'rxjs/BehaviorSubject' ; import * as firebase from 'firebase' ; @ Injectable ( ) export class FirestoreService { private moderatorsPath : string ; private roomMessagesPath : string ; private roomMetadataPath : string ; private roomUsersPath : string ; private suspensionsPath : string ; private userNamesOnlinePath : string ; private usersPath : string ; private roomsRef : AngularFirestoreCollection < Room > ; private usersRef : AngularFirestoreCollection < User > ; constructor ( private afs , private auth ) { this . moderatorsPath = 'moderators' ; this . roomMessagesPath = 'room-messages' ; this . roomMetadataPath = 'room-metadata' ; this . roomUsersPath = 'room-users' ; this . suspensionsPath = 'suspensions' ; this . userNamesOnlinePath = 'user-names-online' ; this . usersPath = 'users' ; this . roomsRef = this . afs . collection < Room > ( this . roomMetadataPath ) ; this . usersRef = this . afs . collection < User > ( this . usersPath ) ; } get timestamp ( ) { return firebase . firestore . FieldValue . serverTimestamp ( ) ; } /** USERS **/ createUser ( user ) { const newUserId = this . afs . createId ( ) ; return this . afs . doc < User > ( `${ this . usersPath }/${ newUserId }` ) . set ( user ) ; } getUser ( userId ) { return this . afs . doc < User > ( `${ this . usersPath }/${ userId }` ) . valueChanges ( ) ; } removeUser ( user ) { return this . afs . doc < User > ( `${ this . usersPath }/${ user . id }` ) . delete ( ) ; } updateUser ( user ) { return this . afs . doc < User > ( `${ this . usersPath }/${ user . id }` ) . update ( user ) ; } /** ROOM METADATA **/ getRooms ( ) { return this . roomsRef . valueChanges ( ) ; } async createRoom ( room ) { const newRoomId = this . afs . createId ( ) ; room . id = newRoomId ; room . createdAt = this . timestamp ; room . createdByUserId = this . auth . id ; room . authorizedUsers = { } ; room . authorizedUsers [ this . auth . id ] = true ; const promise = this . afs . doc < Room > ( `${ this . roomMetadataPath }/${ newRoomId }` ) . set ( room ) ; await promise . then ( result => { console . log ( 'created new room' , result ) ; } , err => console . error ( err , 'You do not have access!' ) ) ; return newRoomId ; } getRoom ( roomId ) { const roomPath = `${ this . roomMetadataPath }/${ roomId }` ; return this . afs . doc < Room > ( roomPath ) . valueChanges ( ) ; } removeRoom ( room ) { const roomPath = `${ this . roomMetadataPath }/${ room . id }` ; return this . afs . doc < Room > ( roomPath ) . delete ( ) ; } updateRoom ( room ) { const roomPath = `${ this . roomMetadataPath }/${ room . id }` ; return this . afs . doc < Room > ( roomPath ) . update ( room ) ; } /** ROOM MESSAGES **/ createRoomMessage ( roomId , message ) { const newMessageId = this . afs . createId ( ) ; const messagePath = `${ this . roomMessagesPath }/${ roomId }/TRANSLATE/${ newMessageId }` ; message . id = newMessageId ; message . timestamp = this . timestamp ; return this . afs . doc < Message > ( messagePath ) . set ( message ) ; } getRoomMessages ( roomId ) { return this . afs . collection < Message > ( `${ this . roomMessagesPath }/${ roomId }/OUTPUT` ) . valueChanges ( ) ; } getRoomMessagesByQuery ( roomId , language$ ) { return language$ . switchMap ( language => { return this . afs . collection < Message > ( `${ this . roomMessagesPath }/${ roomId }/OUTPUT` , ref => language ? ref . where ( 'language' , '==' , language ) . orderBy ( 'timestamp' ) : ref ) . valueChanges ( ) ; } ) ; } removeRoomMessage ( roomId , message ) { return this . afs . doc ( `${ this . roomMessagesPath }/${ roomId }/SOURCE/${ message . id }` ) . delete ( ) ; } updateRoomMessage ( roomId , message ) { return this . afs . doc < Message > ( `${ this . roomMessagesPath }/${ roomId }/SOURCE/${ message . id }` ) . update ( message ) ; } deleteRoomMessages ( roomId ) { return this . deleteCollection ( firebase . database , this . afs . collection ( `${ this . roomMessagesPath }/${ roomId }/SOURCE` ) , 25 ) ; } /** ROOM USERS **/ createRoomUser ( roomId , user ) { return this . afs . doc < User > ( `${ this . roomUsersPath }/${ roomId }/users/${ user . id }` ) . set ( user ) ; } getRoomUsers ( roomId ) { return this . afs . collection < User > ( `${ this . roomUsersPath }/${ roomId }/users` ) . valueChanges ( ) ; } removeRoomUser ( roomId , user ) { return this . afs . doc < User > ( `${ this . roomUsersPath }/${ roomId }/users/${ user . id }` ) . delete ( ) ; } updateRoomUser ( roomId , user , changes ) { return this . afs . doc ( `${ this . roomUsersPath }/${ roomId }/users/${ user . id }` ) . update ( user ) ; } /**
     * Delete a collection, in batches of batchSize. Note that this does
     * not recursively delete subcollections of documents in the collection
     */ private deleteCollection ( db , collectionRef , batchSize ) { const query = collectionRef . orderBy ( '__name__' ) . limit ( batchSize ) ; return new Promise ( ( resolve , reject ) => { this . deleteQueryBatch ( db , query , batchSize , resolve , reject ) ; } ) ; } private deleteQueryBatch ( db , query , batchSize , resolve , reject ) { query . get ( ) . then ( ( snapshot ) => { if ( snapshot . size === 0 ) { return 0 ; } const batch = db . batch ( ) ; snapshot . docs . forEach ( ( doc ) => { batch . delete ( doc . ref ) ; } ) ; return batch . commit ( ) . then ( ( ) => { return snapshot . size ; } ) ; } ) . then ( ( numDeleted ) => { if ( numDeleted <= batchSize ) { resolve ( ) ; return ; } this . deleteQueryBatch ( db , query , batchSize , resolve , reject ) ; } ) . catch ( reject ) ; } private loadUserMetadata ( onComplete ) { } private setupDataEvents ( ) { } private addEventCallback ( eventId , callback ) { } private getEventCallbacks ( eventId ) { } private invokeEventCallbacks ( eventId ) { } private queuePresenceOperation ( ref , onlineValue , offlineValue ) { } private removePresenceOperation ( ref , value ) { } private onUpdateUser ( snapshot ) { } private onAuthRequired ( ) { } private onEnterRoom ( room ) { } private onNewMessage ( roomId , snapshot ) { } private onRemoveMessage ( roomId , snapshot ) { } private onLeaveRoom ( roomId ) { } private onNotification ( snapshot ) { } private onFirechatInvite ( snapshot ) { } private onFirechatInviteResponse ( snapshot ) { } public setUser ( userId , userName , callback ) { } public resumeSession ( ) { } public on ( eventType , cb ) { } public enterRoom ( roomId ) { } public leaveRoom ( roomId ) { } public sendMessage ( roomId , messageContent , messageType , cb ) { } public deleteMessage ( roomId , messageId , cb ) { } public toggleUserMute ( userId , cb ) { } public sendSuperuserNotification ( userId , notificationType , data , cb ) { } public warnUser ( userId ) { } public suspendUser ( userId , timeLengthSeconds , cb ) { } public inviteUser ( userId , roomId ) { } public acceptInvite ( inviteId , cb ) { } public declineInvite ( inviteId , cb ) { } public getRoomList ( cb ) { } public getUsersByRoom ( ) { } public getUsersByPrefix ( prefix , startAt , endAt , limit , cb ) { } public userIsModerator ( ) { } public warn ( msg ) { } }