/*!
 * VisualEditor annotated text content state chunk class
 *
 * @copyright See AUTHORS.txt
 */

/**
 * Uniformly annotated chunk of text content
 *
 * @class
 *
 * @constructor
 * @param {string} text Plain text
 * @param {HTMLElement[]} elements Annotation elements in force
 * @param {string} type If this is a unicorn then 'unicorn', else 'text'
 */
ve.ce.TextStateChunk = function VeCeTextStateChunk( text, elements, type ) {
	/**
	 * @property {string} text The plain text of this chunk
	 */
	this.text = text;

	/**
	 * @property {HTMLElement[]} elements The annotation elements open at this chunk
	 */
	this.elements = elements;

	/**
	 * @property {string} type The chunk type: 'text' or 'unicorn'
	 */
	this.type = type;
};

/* Inheritance */

OO.initClass( ve.ce.TextStateChunk );

/* Static methods */

/**
 * Test whether two elements are equal as annotations.
 * TODO: Improve this test. Currently annotations are compared by tag name and
 * certain attributes, which results in a stricter test than that of
 * ve.dm.ModelRegistry#matchElement . That is, a element pair that tests unequal
 * here might still both match the same ve.dm.Annotation object.
 *
 * @static
 * @param {HTMLElement} element1 An annotation element
 * @param {HTMLElement} element2 Another annotation element
 * @return {boolean} True if the elements are equal as annotations
 */
ve.ce.TextStateChunk.static.compareElements = function ( element1, element2 ) {
	return element1 === element2 || (
		element1.nodeName === element2.nodeName &&
		element1.getAttribute( 'class' ) === element2.getAttribute( 'class' ) &&
		element1.getAttribute( 'typeof' ) === element2.getAttribute( 'typeof' ) &&
		element1.getAttribute( 'property' ) === element2.getAttribute( 'property' ) &&
		element1.getAttribute( 'href' ) === element2.getAttribute( 'href' )
	);
};

/* Methods */

/**
 * Test whether this chunk has the same annotations (in order) as another
 *
 * @param {ve.ce.TextStateChunk} other The other chunk
 * @return {boolean} True if the chunks have the same annotations
 */
ve.ce.TextStateChunk.prototype.hasEqualElements = function ( other ) {
	if ( this.elements === other.elements ) {
		return true;
	}
	if ( this.elements.length !== other.elements.length ) {
		return false;
	}
	for ( let i = 0, len = this.elements.length; i < len; i++ ) {
		if ( !this.constructor.static.compareElements( this.elements[ i ], other.elements[ i ] ) ) {
			return false;
		}
	}
	return true;
};

/**
 * Test whether this chunk is equal to another chunk in both elements and text.
 *
 * @param {ve.ce.TextStateChunk} other The other chunk
 * @return {boolean} True if the chunks are equal
 */
ve.ce.TextStateChunk.prototype.isEqual = function ( other ) {
	return this.text === other.text && this.type === other.type && this.hasEqualElements( other );
};