Source: ReactViews/Custom/CustomComponentType.js

'use strict';

import defined from 'terriajs-cesium/Source/Core/defined';
import DeveloperError from 'terriajs-cesium/Source/Core/DeveloperError';

/**
 * Represents a custom component type, eg. <chart>.
 *
 * @alias CustomComponentType
 * @constructor
 * @param {Object} options Options.
 * @param {String} options.name The component's name, eg. 'chart'.
 */
const CustomComponentType = function(options) {

    if (!defined(options.name)) {
        throw new DeveloperError('Custom components must have a name.');
    }

    if (!defined(options.processNode)) {
        throw new DeveloperError('Custom components must have a processNode method.');
    }

    /**
     * Gets or sets the tag name, eg. "chart". This is converted to lower case.
     * @type {String}
     */
    this.name = options.name.toLowerCase();

    /**
     * Gets or sets the custom attributes for this tag, eg. ["src-preview"].
     * Used so that when the user-supplied html is sanitized, these attributes are not stripped.
     * @type {String[]}
     */
    this.attributes = options.attributes;

    /**
     * Gets or sets a function which is called when an element of this custom component is created.
     * @type {CustomComponentType~processNode}
     */
    this.processNode = options.processNode;

    /**
     * Gets or sets an array of objects with additional processNode and shouldProcessNode functions, as above.
     * @type {Object[]}
     */
    this.furtherProcessing = options.furtherProcessing;

    /**
     * Gets or sets a function which checks a ReactComponent and returns a Boolean indicating if that react component
     * corresponds to this type.
     * "Correspondence" is whatever the component wants it to be. It is used by CustomComponents.find.
     * CustomComponents.find is used by the feature info template to find if any custom components self-update.
     * @type {CustomComponentType~isCorresponding}
     */
    this.isCorresponding = options.isCorresponding || (reactComponent=>undefined);

    /**
     * Gets or sets a function which checks a ReactComponent and returns an integer if it both
     * contains this custom component type, and that component would self-update (eg. from a "poll-seconds" attribute).
     * @type {CustomComponentType~selfUpdateSeconds}
     */
    this.selfUpdateSeconds = options.selfUpdateSeconds || (reactComponent=>undefined);

    /**
     * A function passed to html-to-react's processingInstructions.
     *
     * @callback CustomComponentType~processNode
     * @param {Object} context Context for the custom component.
     * @param {CatalogMember} [context.catalogItem] The catalog item for which this chart is being requested.
     * @param {Feature} [context.feature] The feature for which this chart is being requested.
     * @param {Object} [context.updateCounters] Used for self-updating components. An object whose keys are timeoutIds, and whose values are
     *                   {reactComponent: ReactComponent, counter: Integer}. reactComponent is selected by this.isCorresponding.
     * @param {Object} node A description of the node in html, eg. {type: "tag", name: "chart", attribs: {src: "filename.csv"}, children: [], next: null, parent: null, prev: null}
     * @param {Object[]} children The node's children.
     */

    /**
     * Gets or sets a function which checks a ReactComponent and returns a Boolean indicating if that react component
     * corresponds to this type.
     *
     * @callback CustomComponentType~isCorresponding
     * @param {ReactComponent} reactComponent This react component.
     * @returns {Boolean} Does the given react component correspond to this custom component type?
     */

    /**
     * A function which checks a ReactComponent and returns an integer if it both
     * contains this custom component type, and that component would self-update (eg. from a "poll-seconds" attribute).
     *
     * @callback CustomComponentType~selfUpdateSeconds
     * @param {ReactComponent} reactComponent This react component.
     * @returns {Integer} The number of seconds between updates of this component, or undefined.
     */

};

module.exports = CustomComponentType;