import { Subject } from "../observe/Observable"; import { Observer } from "../observe/Observer"; import { JsonAPI } from "../singleton/JsonAPI"; import { ChatMessageViewModel } from "../viewmodel/ChatMessageViewModel"; import { ChatModelHelper } from "./ChatModelHelper"; import log = require('loglevel'); import { ObserverData } from "../observe/ObserverData"; interface Params { userName: string, data: ChatMessageViewModel[], op: string } export class ChatModel implements Subject { /** * @type {Observer[]} List of subscribers. In real life, the list of * subscribers can be stored more comprehensively (categorized by event * type, etc.). */ private readonly _observers: Observer[] = []; private readonly _messagePageMap: Map; private readonly _messagesMap: Map; private readonly _chatModelHelper: ChatModelHelper; constructor(chatModelHelper: ChatModelHelper) { this._messagePageMap = new Map(); this._messagesMap = new Map(); this._chatModelHelper = chatModelHelper; } /** * The subscription management methods. */ public attach(observer: Observer): void { log.info('Subject: Attached an observer.'); this._observers.push(observer); } public detach(observer: Observer): void { const observerIndex = this._observers.indexOf(observer); this._observers.splice(observerIndex, 1); log.info('Subject: Detached an observer.'); } private storeUserMessages(username: string, messages: ChatMessageViewModel[], op: string) { switch (op) { case "clear": this._messagesMap.set(username, []); case "page": this._messagesMap.set(username, messages.concat(this.getStoredUserMessages(username))); break; // case "page": this._messagesMap.set(username, messages); case "new": this._messagesMap.set(username, this.getStoredUserMessages(username).concat(messages)); break; default: new Error("Invalid option"); } } private getStoredUserMessages(username: string): ChatMessageViewModel[] { let temp = this._messagesMap.get(username); if (temp == null) return []; else { return temp; } } /** * Trigger an update in each subscriber. */ public notify(p: Params): void { log.info('Subject: Notifying observers...'); switch (p.op) { case "clear": { const od: ObserverData = { data: [], op: "clear" } for (const observer of this._observers) { observer.update(od); } } break; case "new": { const od: ObserverData = { data: p.data, op: p.op } for (const observer of this._observers) { observer.update(od); } } break; case "page": { const od: ObserverData = { data: p.data, op: p.op } for (const observer of this._observers) { observer.update(od); } } break; default: { log.error("error") } } } public someBusinessMethod(chatMessageList: ChatMessageViewModel[]): void { } public clear(): void { log.info("Clearing model") this._messagePageMap.set(JsonAPI.contactName!, 0); this.storeUserMessages(JsonAPI.contactName!, Array(), "clear"); this.notify({ userName: "", data: [], op: "clear" }) } public async getMessages(contactName: string, passphrase: string, lastMessageTime: string | null, op: string): Promise { if (this._messagePageMap.get(contactName) == null) this._messagePageMap.set(contactName, 0); const pageNumber = this._messagePageMap.get(contactName) const cVMs = await this._chatModelHelper.getMessages(contactName, passphrase, pageNumber!, lastMessageTime, op); if (cVMs != null) { log.info('Subject: My state has just changed') const existingMessages = this.getStoredUserMessages(contactName); log.debug('existing message:') log.debug(existingMessages); log.debug('new messages:') log.debug(cVMs); this.storeUserMessages(contactName, cVMs, op); this.notify({ userName: contactName, data: cVMs, op: op }); } else { log.error('Messages were null'); } if (cVMs.length != 0) { this._messagePageMap.set(contactName, this._messagePageMap.get(contactName)! + 1); } return cVMs; } }