// src/framework/shadowlisp/index.ts
//
// Vision 48: ShadowLisp Element Registration
//
// John McCarthy (LISP creator, Turing Award 1971):
//   "The browser's DOM IS an S-expression tree. We just needed
//    custom elements to make it explicit."
//
// Exports all ShadowLisp elements for use in applications.

// Core elements
export { SlForm } from './SlForm';
export { SlAtom, type AtomKind } from './SlAtom';
export { SlRuntime, Environment } from './SlRuntime';
export { SlModule } from './SlModule';
export { SlDomRenderer, type IRenderContext } from './SlDomRenderer';

// Phase 4: Advanced Lisp features
export { SlMacroExpander, type MacroTransformer } from './SlMacro';
export {
  SlContinuationContext,
  CPSEvaluator,
  makePromptTag,
  DEFAULT_PROMPT,
  type Continuation,
  type PromptTag
} from './SlContinuation';
export {
  SlEffectContext,
  SlEffectEvaluator,
  StandardEffects,
  createHandler,
  PerformedEffect,
  type EffectHandler,
  type IEffectOp,
  type IEffectSignature,
  type IHandlerDef
} from './SlEffects';

// Re-export SExpr type for convenience
export type { SExpr } from '../../lisp/SExpr';

function logShadowLispRegistration(message: string): void {
  // eslint-disable-next-line no-console -- kernel ShadowLisp registration has no actor context
  console.log(message);
}

/**
 * Ensure all ShadowLisp elements are registered.
 * Call this once at application startup.
 *
 * @example
 * import { registerShadowLispElements } from '../framework/shadowlisp';
 * registerShadowLispElements();
 */
export function registerShadowLispElements(): void {
  // Elements self-register on import, but this ensures they're loaded
  // Import side-effects register the custom elements
  void import('./SlAtom');
  void import('./SlForm');
  void import('./SlRuntime');
  void import('./SlModule');

  logShadowLispRegistration('[ShadowLisp] Elements registered: sl-atom, sl-form, sl-runtime, sl-module');
}

/**
 * Check if ShadowLisp elements are registered.
 */
export function areShadowLispElementsRegistered(): boolean {
  return !!(
    customElements.get('sl-atom') &&
    customElements.get('sl-form') &&
    customElements.get('sl-runtime') &&
    customElements.get('sl-module')
  );
}

/**
 * Create an S-expression from DOM elements.
 * Convenience function for extracting S-expr from existing DOM.
 *
 * @param element - DOM element containing sl-form/sl-atom
 * @returns S-expression
 */
export function domToSExpr(element: Element): import('../../lisp/SExpr').SExpr {
  if (element.tagName === 'SL-FORM') {
    return (element as unknown as import('./SlForm').SlForm).toSExpr();
  }
  if (element.tagName === 'SL-ATOM') {
    return (element as unknown as import('./SlAtom').SlAtom).toSExpr();
  }
  throw new Error(`Cannot convert ${element.tagName} to S-expression`);
}

/**
 * Create DOM elements from an S-expression.
 * Convenience function for building DOM from S-expr.
 *
 * @param sexp - S-expression
 * @returns DOM element (SlForm or SlAtom)
 */
export function sExprToDom(sexp: import('../../lisp/SExpr').SExpr): Element {
  const { SlForm } = require('./SlForm');
  return SlForm.fromSExpr(sexp);
}
