// PresetControlPanel: the thin, controlled editor. For the active preset it
// renders that preset's `controls` component (keyed by preset id, so a switch
// remounts and the ControlForms re-seed), handing it the per-layer baked
// uniforms and a single shared onPatch. It never calls `kaleidoscope` itself;
// the host routes onPatch into `kaleidoscope(activeId, [patch])`.

import type { ReactElement } from 'react';
import type {
  KaleidoscopeControls,
  KaleidoscopePresetBook,
} from '../../kaleidoscope.preset-book.types';
import { ControlScopeContext } from '../form/scope';

export type PresetControlPanelProps<P extends KaleidoscopePresetBook> = {
  readonly presets: P;
  /** The active preset id, or null when nothing is selected. */
  readonly value: (keyof P & string) | null;
  /** Routed to the host, which applies it via `kaleidoscope(value, [patch])`. */
  readonly onPatch: KaleidoscopeControls['onPatch'];
  /**
   * Per-layer uniform overrides (e.g. a persisted selection's stored patches)
   * merged over the preset's baked uniforms when the forms seed. Seed-time
   * only: the forms re-seed on a preset switch, not when this prop changes
   * mid-mount, so hosts restoring persisted patches should mount the panel
   * after hydration.
   */
  readonly patches?: KaleidoscopeControls['uniforms'];
  readonly disabled?: boolean;
};

export function PresetControlPanel<P extends KaleidoscopePresetBook>({
  presets,
  value,
  onPatch,
  patches,
  disabled = false,
}: PresetControlPanelProps<P>): ReactElement | null {
  if (value === null) return null;
  const preset = presets[value];
  const Controls = preset?.controls;
  if (!Controls) return null;

  // Per-layer baked uniforms keyed by id, for the controls component to seed each
  // layer's ControlForm. Only tunable layers carry uniforms; stored overrides
  // merge over the baked values so restored tweaks appear in the forms.
  const uniforms: Record<string, Record<string, number | readonly number[]>> = {};
  for (const layer of preset.layers) {
    if ('uniforms' in layer) {
      uniforms[layer.id] = {
        ...layer.uniforms,
        ...patches?.[layer.id],
      } as Record<string, number | readonly number[]>;
    }
  }

  return (
    <ControlScopeContext.Provider value={value}>
      <Controls key={value} uniforms={uniforms} onPatch={onPatch} disabled={disabled} />
    </ControlScopeContext.Provider>
  );
}
