'use strict';

Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });

const constants = require('../constants.cjs');
const internals = require('./internals.cjs');

/**
 * A custom element that represents the root of a remote tree of elements.
 * To use this element, define it as a custom element and create it with
 * `document.createElement()`. Then, call its `connect()` method with a
 * `RemoteConnection` instance from a host environment, and start appending
 * child nodes to the tree. Any changes to the tree nested under this element
 * will be synchronized with the host environment automatically.
 *
 * @example
 * ```ts
 * import {RemoteRootElement} from '@remote-dom/core/elements';
 *
 * customElements.define('remote-root', RemoteRootElement);
 *
 * const element = document.createElement('remote-root');
 *
 * withRemoteConnectionFromHost((connection) => {
 *   element.connect(connection);
 * });
 *
 * element.append('Hello world!');
 */
class RemoteRootElement extends HTMLElement {
  constructor() {
    super();
    internals.setRemoteId(this, constants.ROOT_ID);
  }
  connect(connection) {
    if (internals.remoteConnection(this) === connection) return;
    internals.connectRemoteNode(this, connection);
    if (this.childNodes.length === 0) return;
    const records = [];
    for (let i = 0; i < this.childNodes.length; i++) {
      const node = this.childNodes[i];
      records.push([constants.MUTATION_TYPE_INSERT_CHILD, constants.ROOT_ID, internals.serializeRemoteNode(node), i]);
    }
    connection.mutate(records);
  }
  updateRemoteProperty(name, value) {
    internals.updateRemoteElementProperty(this, name, value);
  }
  callRemoteMethod(method, ...args) {
    return internals.callRemoteElementMethod(this, method, ...args);
  }
}

exports.RemoteRootElement = RemoteRootElement;
