/*!
 * VisualEditor ContentEditable Annotation class.
 *
 * @copyright See AUTHORS.txt
 */

/**
 * Generic ContentEditable annotation.
 *
 * This is an abstract class, annotations should extend this and call this constructor from their
 * constructor. You should not instantiate this class directly.
 *
 * Subclasses of ve.dm.Annotation should have a corresponding subclass here that controls rendering.
 *
 * @abstract
 * @extends ve.ce.View
 *
 * @constructor
 * @param {ve.dm.Annotation} model Model to observe
 * @param {ve.ce.ContentBranchNode} [parentNode] Node rendering this annotation
 * @param {Object} [config] Configuration options
 */
ve.ce.Annotation = function VeCeAnnotation( model, parentNode, config = {} ) {
	// Parent constructor
	ve.ce.Annotation.super.call( this, model, config );

	// Properties
	this.parentNode = parentNode || null;

	this.$element
		// Make data available before setup
		.data( 'view', this )
		.addClass( 've-ce-annotation' );
};

/* Inheritance */

OO.inheritClass( ve.ce.Annotation, ve.ce.View );

/* Static Properties */

ve.ce.Annotation.static.tagName = 'span';

/**
 * Annotations which can be active get a ve-ce-annotation-active class when focused.
 */
ve.ce.Annotation.static.canBeActive = false;

/* Static Methods */

/**
 * Get a plain text description.
 *
 * @static
 * @inheritable
 * @param {ve.dm.Annotation} annotation Annotation model
 * @return {string} Description of annotation
 */
ve.ce.Annotation.static.getDescription = function () {
	return '';
};

/* Methods */

/**
 * Get the content branch node this annotation is rendered in, if any.
 *
 * @return {ve.ce.ContentBranchNode|null} Content branch node or null if none
 */
ve.ce.Annotation.prototype.getParentNode = function () {
	return this.parentNode;
};

/**
 * @inheritdoc
 */
ve.ce.Annotation.prototype.getModelHtmlDocument = function () {
	return this.parentNode && this.parentNode.getModelHtmlDocument();
};

/**
 * Append a child node to the annotation
 *
 * @param {Node} childNode Child node to append
 */
ve.ce.Annotation.prototype.appendChild = function ( childNode ) {
	this.$element[ 0 ].appendChild( childNode );
};

/**
 * Get the container into which annotation contents should be appended
 *
 * @return {HTMLElement} Content container
 */
ve.ce.Annotation.prototype.getContentContainer = function () {
	return this.$element[ 0 ];
};

/**
 * Attach completed contents to the annotation as descendant nodes, if not already attached
 *
 * No further contents should be appended into the content container after calling this
 */
ve.ce.Annotation.prototype.attachContents = function () {
	// Do nothing; already attached
};

/**
 * Append the completed annotation to a parent node
 *
 * #attachContents should have been called first
 *
 * @param {Node} node Parent node
 */
ve.ce.Annotation.prototype.appendTo = function ( node ) {
	node.appendChild( this.$element[ 0 ] );
};

/**
 * Check if the annotation can be active
 *
 * @return {boolean}
 */
ve.ce.Annotation.prototype.canBeActive = function () {
	return this.constructor.static.canBeActive;
};

/**
 * Release all memory
 */
ve.ce.Annotation.prototype.destroy = function () {
	this.parentNode = null;

	// Parent method
	ve.ce.Annotation.super.prototype.destroy.call( this );
};
