// src/lisp/primitives/index.ts
// Central export for all LISP primitives
//
// Organized into categories following the LISP-RESTRUCTURE-PLAN.md:
// - McCarthy's 7 + eq (foundational)
// - Arithmetic (math operations)
// - Comparison (relational operators)
// - Boolean (logical operators)
// - List (list manipulation)
// - Higher-Order (functional programming)
// - String (text operations)
// - Stream (reactive streams)
// - Matrix (component bridge)
// - Meta (metaprogramming)
// - Serialization (5-representation parity)

import type { IPrimitiveDefinition, PrimitiveHandler } from './mccarthy';

// Import all primitive collections
import { mccarthyPrimitives } from './mccarthy';
import { arithmeticPrimitives } from './arithmetic';
import { comparisonPrimitives } from './comparison';
import { booleanPrimitives } from './boolean';
import { listPrimitives } from './list';
import { higherOrderPrimitives } from './higher-order';
import { stringPrimitives } from './string';
import { streamPrimitives } from './stream';
import { matrixPrimitives } from './matrix';
import { metaPrimitives } from './meta';
import { serializationPrimitives } from './serialization';

// Re-export types
export type { IPrimitiveDefinition, PrimitiveHandler };

// Re-export individual collections for selective imports
export { mccarthyPrimitives } from './mccarthy';
export { arithmeticPrimitives } from './arithmetic';
export { comparisonPrimitives } from './comparison';
export { booleanPrimitives } from './boolean';
export { listPrimitives } from './list';
export { higherOrderPrimitives } from './higher-order';
export { stringPrimitives } from './string';
export { streamPrimitives } from './stream';
export { matrixPrimitives } from './matrix';
export { metaPrimitives } from './meta';
export { serializationPrimitives } from './serialization';

/**
 * All primitives combined into a single array
 * Total: ~118 primitives across 11 categories
 */
export const allPrimitives: IPrimitiveDefinition[] = [
  ...mccarthyPrimitives,     // 10: quote, atom, eq, car, cdr, cons, cond, cadr, caddr, cadddr
  ...arithmeticPrimitives,   // 20: +, -, *, /, mod, abs, min, max, floor, ceil, round, sqrt, pow, exp, log, log10, sin, cos, tan, random
  ...comparisonPrimitives,   // 5: >, <, =, >=, <=
  ...booleanPrimitives,      // 3: and, or, not
  ...listPrimitives,         // 18: list, length, nth, last, butlast, append, reverse, member, range, take, drop, sort, zip, unique, flatten, null?, pair?, list?
  ...higherOrderPrimitives,  // 13: map, filter, reduce, find, every, some, compose, partial, curry, juxt, complement, identity, constantly
  ...stringPrimitives,       // 15: concat, substring, split, join, upper, lower, trim, replace, starts-with, ends-with, includes, index-of, char-at, string?, format
  ...streamPrimitives,       // 12: stream-of, stream-map, stream-filter, stream-scan, stream-debounce, stream-throttle, stream-take, stream-distinct, stream-tap, stream-merge, stream-to, stream?
  ...matrixPrimitives,       // 16: call, emit, spawn, destroy, introspect, list-spawned, subscribe, unsubscribe, get, set, keys, values, entries, obj, merge, object?
  ...metaPrimitives,         // 32: eval, apply, lambda, define, let, let*, letrec, if, when, unless, case, do, quasiquote, defmacro, macroexpand, gensym, try, throw, type predicates, conversions, json, time, debug, ->
  ...serializationPrimitives, // 6: to-sexpr, to-html, to-json, to-fluent, to-topics, serialize
];

/**
 * Build a lookup map for O(1) primitive access
 * Maps both primary names and aliases to their definitions
 */
export function buildPrimitiveMap(primitives: IPrimitiveDefinition[] = allPrimitives): Map<string, IPrimitiveDefinition> {
  const map = new Map<string, IPrimitiveDefinition>();

  for (const prim of primitives) {
    map.set(prim.name, prim);
    if (prim.aliases) {
      for (const alias of prim.aliases) {
        map.set(alias, prim);
      }
    }
  }

  return map;
}

/**
 * Default primitive map with all primitives
 */
export const primitiveMap = buildPrimitiveMap();

/**
 * Check if a name is a primitive
 */
export function isPrimitive(name: string): boolean {
  return primitiveMap.has(name);
}

/**
 * Get a primitive by name or alias
 */
export function getPrimitive(name: string): IPrimitiveDefinition | undefined {
  return primitiveMap.get(name);
}

/**
 * Get all primitive names (including aliases)
 */
export function getAllPrimitiveNames(): string[] {
  return Array.from(primitiveMap.keys());
}

/**
 * Get only primary primitive names (no aliases)
 */
export function getPrimaryPrimitiveNames(): string[] {
  return allPrimitives.map(p => p.name);
}

/**
 * Group primitives by category for documentation/introspection
 */
export const primitivesByCategory = {
  mccarthy: mccarthyPrimitives,
  arithmetic: arithmeticPrimitives,
  comparison: comparisonPrimitives,
  boolean: booleanPrimitives,
  list: listPrimitives,
  higherOrder: higherOrderPrimitives,
  string: stringPrimitives,
  stream: streamPrimitives,
  matrix: matrixPrimitives,
  meta: metaPrimitives,
  serialization: serializationPrimitives,
} as const;

/**
 * Category names for iteration
 */
export const categoryNames = Object.keys(primitivesByCategory) as (keyof typeof primitivesByCategory)[];
