import htm from 'htm/mini';

const htmlInner = htm.bind(h);
function html(strings, ...values) {
  return normalizeComponentReturn(htmlInner(strings, ...values));
}
// Inspired by https://github.com/developit/vhtml
function h(name, properties, ...children) {
  let childNodes = normalizeComponentReturn(children);

  // Pseudo-components, where they get DOM nodes as children.
  if (typeof name === 'function') {
    const resolvedProperties = properties ?? {};
    resolvedProperties.children = childNodes;
    return normalizeComponentReturn(name(resolvedProperties));
  }
  const element = document.createElement(name);
  if (properties) {
    for (const property in properties) {
      const value = properties[property];
      if (value instanceof Node) {
        childNodes ??= [];
        const fragment = document.createElement('remote-fragment');
        fragment.slot = property;
        fragment.append(value);
        childNodes.push(fragment);
      } else if (property in element) {
        element[property] = value;
      } else if (property[0] === 'o' && property[1] === 'n') {
        const eventName = `${property[2].toLowerCase()}${property.slice(3)}`;
        element.addEventListener(eventName, value);
      } else if (value === true) {
        element.setAttribute(property, '');
      } else if (value == null || value === false) {
        element.removeAttribute(property);
      } else {
        element.setAttribute(property, String(value));
      }
    }
  }
  if (childNodes) element.append(...childNodes);
  return element;
}
function normalizeComponentReturn(result) {
  let normalized;
  if (Array.isArray(result)) {
    normalized = [];
    for (const item of result.flat()) {
      const normalizedItem = normalizedComponentReturnItem(item);
      if (normalizedItem) normalized.push(normalizedItem);
    }
  } else {
    normalized = normalizedComponentReturnItem(result);
  }
  if (Array.isArray(normalized) && normalized.length === 0) {
    return null;
  }
  return normalized;
}
function normalizedComponentReturnItem(value) {
  return typeof value === 'string' || typeof value === 'number' ? document.createTextNode(String(value)) : value || null;
}

export { h, html };
