Home Reference Source

src/contacts/GroupContact.js

import {EventEmitter} from '../eventemitter';
import {BaseContact} from './BaseContact';
import {
	updateContact,
	removeContact,
} from './utils';

const isValidParticipants = participants =>
	!(Array.isArray(participants) && participants.length > 0);

/**
 * Represents a group contact. This class must not be directly instantiated. Instead,
 * instances of this class are obtained by calling the {@link ContactManager#createGroupContact}
 * or {@link ContactManager#getContacts} methods of {ContactManager}
 *
 * ## Events
 *
 * - **`update`** is emitted every time the contact is updated.
 * - **`delete`** is emitted when the contact is deleted.
 */
export class GroupContact extends EventEmitter {

	/**
	 * Constructs a new contact
	 * @protected
	 * @param {WacStack} stack
	 * @param {Object} data
	 * @param {string} data.id
	 * @param {string} data.name
	 * @param {string} data.source
	 * @param {boolean} data.favorite
	 * @param {Object[]} data.participants
	 * @property {string} data.participants.name
	 * @property {string} data.participants.address
	 */
	constructor(stack, data = {}) {
		super();

		/**
		 * @type {WacStack}
		 */
		this._stack = stack;

		/**
		 * @type {BaseContact}
		 * @private
		 */
		this._base = BaseContact.create(data);

		/**
		 * @type {Object[]}
		 */
		this._participants = data.participants || [];
	}

	/**
	 * Contact unique identifier
	 * @type {string}
	 */
	get id() {
		return this._base.getId();
	}

	/**
	 * Name associated with this contact
	 * @type {string}
	 */
	get name() {
		return this._base.getName();
	}

	/**
	 * Source name of the contact's source
	 * @type {string}
	 */
	get source() {
		return this._base.getSource();
	}

	/*
	 * @type {boolean}
	 */
	get favorite() {
		return this._base.isFavorite();
	}

	/**
	 * Source name of the contact's source
	 * @type {string}
	 */
	get participants() {
		return this._participants;
	}


	/**
	 * Display name associated with this contact
	 * @type {string}
	 */
	set name(name) {
		this._base.setName(name);
		updateContact(this._base.getId(), this._stack, this.toJSON());
	}

	/**
	 * Whether the contact is favorite
	 * @type {boolean}
	 */
	set favorite(favorite) {
		this._base.setFavorite(favorite);
		updateContact(this._base.getId(), this._stack, this.toJSON());
	}

	/**
	 * Update the participants
	 * @type {boolean}
	 */
	set participants(participants) {
		if (isValidParticipants(participants)) {
			throw Error('participants must be an array');
		}
		this._participants = participants;
		updateContact(this._base.getId(), this._stack, this.toJSON());
	}


	/**
	 * Removes the contact
	 * @return {Promise<undefined,Error>}
	 */
	remove() {
		return removeContact(this._base.getId(), this._stack)
			.then(() => this._remove());
	}

	/**
	 * Updates the contact with the new data
	 * @protected
	 * @param {Contact} contact
	 */
	_update(contact) {
		this._base.setName(contact.name);
		this._base.setFavorite(contact.favorite);
		this._participants = contact.participants;
		this.emit('update');
	}

	/**
	 * Removes (locally) the contact
	 * @protected
	 */
	_remove() {
		this._stack = null;
		this.emit('delete');
	}

	/**
	 * Returns a JS object with the JSON serialization representation of this object
	 */
	toJSON() {
		return {
			id: this.id,
			name: this.name,
			source: this.source,
			favorite: this.favorite,
			participants: this.participants,
		};
	}
}