<commit_before>import { IContact, ContactType, ContactSubscription } from './Contact.interface'
import Storage from './Storage'
import JID from './JID'
import Account from './Account'
import PersistentMap from './util/PersistentMap'
import IIdentifiable from './Identifiable.interface'
import Log from './util/Log'
import { Presence } from './connection/AbstractConnection'
import { EncryptionState } from './plugin/AbstractPlugin'
import Transcript from './Transcript'
import ChatWindowController from './ChatWindowController'
import Avatar from './Avatar'
import Message from './Message'
import ChatWindow from './ui/ChatWindow';
import ContactProvider from './ContactProvider';
import DiscoInfo from './DiscoInfo';

export default class Contact implements IIdentifiable, IContact {
   protected storage: Storage;

   protected readonly account: Account;

   protected data: PersistentMap;

   protected id: string;

   protected jid: JID;

   protected chatWindow;

   protected chatWindowController;

   protected transcript: Transcript;

   public static getProviderId(account: Account, id: string) {
      let data = new PersistentMap(account.getStorage(), 'contact', id);

      return data.get('provider');
   }

   constructor(account: Account, jid: JID, name?: string);
   constructor(account: Account, id: string);
   constructor() {
      this.account = arguments[0];
      this.storage = this.account.getStorage();

      if (typeof arguments[1] === 'string') {
         this.initExistingContact(arguments[1]);
      } else {
         this.initNewContact(arguments[1], arguments[2]);
      }

      this.id = this.data.get('id');
   }

   private initExistingContact(id: string) {
      this.data = new PersistentMap(this.storage, 'contact', id);

      if (!this.data.get('id')) {
         throw new Error(`Could not find existing contact with id "${id}".`);
      }

      this.jid = new JID(this.data.get('jid'));
   }

   private initNewContact(jid: JID, name?: string) {
      let id = jid.bare;
      this.jid = jid;

      let defaultData = {
         id,
         jid: this.jid.full,
         name: name || this.jid.bare,
         presence: Presence.offline,
         status: '',
         subscription: ContactSubscription.NONE,
         resources: {},
         type: ContactType.CHAT,
         rnd: Math.random() // force storage event
      }

      this.data = new PersistentMap(this.storage, 'contact', id);

      this.data.set(defaultData);
   }

   public async delete() {
      this.data.delete();
   }

   public getChatWindow(): ChatWindow {
      if (!this.chatWindow) {
         this.chatWindow = new ChatWindow(this);
      }

      return this.chatWindow;
   }

   public getChatWindowController(): ChatWindowController {
      if (!this.chatWindowController) {
         this.chatWindowController = new ChatWindowController(this, this.data);
      }

      return this.chatWindowController;
   }

   public getAccount(): Account {
      return this.account;
   }

   public addSystemMessage(messageString: string): Message {
      let message = new Message({
         peer: this.getJid(),
         direction: Message.DIRECTION.SYS,
         plaintextMessage: messageString,
         unread: false,
      });

      this.getTranscript().pushMessage(message);

      return message;
   }

   public setResource = (resource: string) => {
      this.jid = new JID(this.jid.bare + '/' + resource);

      this.data.set('jid', this.jid.full);
   }

   public clearResources() {
      this.data.set('resources', {});
   }

   public setPresence(resource: string, presence: Presence) {
      Log.debug('set presence for ' + this.jid.bare + ' / ' + resource, presence);

      let resources = this.data.get('resources') || {};

      if (presence === Presence.offline) {
         if (resource) {
            delete resources[resource];
         } else {
            resources = {};
         }
      } else if (resource) {
         resources[resource] = presence;
      }

      presence = this.getHighestPresence();
<commit_msg>refactor: resource update<commit_after>import { IContact, ContactType, ContactSubscription } from './Contact.interface'
import Storage from './Storage'
import JID from './JID'
import Account from './Account'
import PersistentMap from './util/PersistentMap'
import IIdentifiable from './Identifiable.interface'
import Log from './util/Log'
import { Presence } from './connection/AbstractConnection'
import { EncryptionState } from './plugin/AbstractPlugin'
import Transcript from './Transcript'
import ChatWindowController from './ChatWindowController'
import Avatar from './Avatar'
import Message from './Message'
import ChatWindow from './ui/ChatWindow';
import ContactProvider from './ContactProvider';
import DiscoInfo from './DiscoInfo';

export default class Contact implements IIdentifiable, IContact {
   protected storage: Storage;

   protected readonly account: Account;

   protected data: PersistentMap;

   protected id: string;

   protected jid: JID;

   protected chatWindow;

   protected chatWindowController;

   protected transcript: Transcript;

   public static getProviderId(account: Account, id: string) {
      let data = new PersistentMap(account.getStorage(), 'contact', id);

      return data.get('provider');
   }

   constructor(account: Account, jid: JID, name?: string);
   constructor(account: Account, id: string);
   constructor() {
      this.account = arguments[0];
      this.storage = this.account.getStorage();

      if (typeof arguments[1] === 'string') {
         this.initExistingContact(arguments[1]);
      } else {
         this.initNewContact(arguments[1], arguments[2]);
      }

      this.id = this.data.get('id');
   }

   private initExistingContact(id: string) {
      this.data = new PersistentMap(this.storage, 'contact', id);

      if (!this.data.get('id')) {
         throw new Error(`Could not find existing contact with id "${id}".`);
      }

      this.jid = new JID(this.data.get('jid'));
   }

   private initNewContact(jid: JID, name?: string) {
      let id = jid.bare;
      this.jid = jid;

      let defaultData = {
         id,
         jid: this.jid.full,
         name: name || this.jid.bare,
         presence: Presence.offline,
         status: '',
         subscription: ContactSubscription.NONE,
         resources: {},
         type: ContactType.CHAT,
         rnd: Math.random() // force storage event
      }

      this.data = new PersistentMap(this.storage, 'contact', id);

      this.data.set(defaultData);
   }

   public async delete() {
      this.data.delete();
   }

   public getChatWindow(): ChatWindow {
      if (!this.chatWindow) {
         this.chatWindow = new ChatWindow(this);
      }

      return this.chatWindow;
   }

   public getChatWindowController(): ChatWindowController {
      if (!this.chatWindowController) {
         this.chatWindowController = new ChatWindowController(this, this.data);
      }

      return this.chatWindowController;
   }

   public getAccount(): Account {
      return this.account;
   }

   public addSystemMessage(messageString: string): Message {
      let message = new Message({
         peer: this.getJid(),
         direction: Message.DIRECTION.SYS,
         plaintextMessage: messageString,
         unread: false,
      });

      this.getTranscript().pushMessage(message);

      return message;
   }

   public setResource = (resource: string) => {
      this.jid = new JID(this.jid.bare + '/' + resource);

      this.data.set('jid', this.jid.full);
   }

   public clearResources() {
      this.data.set('resources', {});
   }

   public setPresence(resource: string, presence: Presence) {
      Log.debug('set presence for ' + this.jid.bare + ' / ' + resource, presence);

      if (resource) {
         let resources = this.data.get('resources') || {};

         if (presence === Presence.offline) {
            delete resources[resource];
         } else {
            resources[resource] = presence;
         }

         this.data.set('resources', resources);
      }

      presence = this.getHighestPresence();

{'fraction_non_alphanumeric': 0.12453806356245381, 'fraction_numerical': 0.001231830500123183, 'mean_word_length': 2.7780362959516056, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, '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': '3253430', 'n_tokens_mistral': 2316, 'n_tokens_neox': 2240, 'n_words': 574}