import type { FieldAlias, FieldId, FieldName } from "./index.js";

export type FieldOptions = Readonly<Record<string, number | string | boolean>>;
export type FieldSampler = (
  x: number,
  y: number,
  time?: number,
  options?: FieldOptions,
  kit?: FieldKit,
) => number;

export const TAU: number;
export const BAYER8_SIZE: 8;
export const BAYER8: readonly number[];
export function clamp(value: number, min?: number, max?: number): number;
export function lerp(a: number, b: number, amount: number): number;
export function smoothstep(edge0: number, edge1: number, value: number): number;
export function smootherstep(edge0: number, edge1: number, value: number): number;
export function fract(value: number): number;
export function bayer8(x: number, y: number): number;
export const bayerThreshold: typeof bayer8;
export function orderedDither(
  value: number,
  x: number,
  y: number,
  levels?: number,
): number;
export function hashSeed(seed?: unknown): number;

export class FieldKit {
  constructor(seed?: unknown | { seed: unknown });
  seed: number;
  readonly permutation: Uint8Array;
  reseed(seed?: unknown): this;
  setSeed(seed?: unknown): this;
  clone(): FieldKit;
  list(): readonly FieldId[];
  has(id: unknown): boolean;
  get(id: FieldName): FieldSampler | undefined;
  sample(
    id: FieldName,
    x: number,
    y: number,
    time?: number,
    options?: FieldOptions,
  ): number;
  hash2(x: number, y: number, salt?: number): number;
  signedNoise2(x: number, y: number): number;
  noise2(x: number, y: number): number;
  signedNoise3(x: number, y: number, z: number): number;
  noise3(x: number, y: number, z: number): number;
  value2(x: number, y: number): number;
  fbmNoise(x: number, y: number, z?: number, options?: FieldOptions): number;
  ridgedNoise(x: number, y: number, z?: number, options?: FieldOptions): number;
  curl2(
    x: number,
    y: number,
    z?: number,
    epsilon?: number,
    out?: Float32Array | number[],
  ): Float32Array | number[];
  cellular2(x: number, y: number, time?: number, options?: FieldOptions): number;
  voronoi2(x: number, y: number, time?: number, options?: FieldOptions): number;
  fbm(x: number, y: number, time?: number, options?: FieldOptions): number;
  ridged(x: number, y: number, time?: number, options?: FieldOptions): number;
  domainWarp(x: number, y: number, time?: number, options?: FieldOptions): number;
  curl(x: number, y: number, time?: number, options?: FieldOptions): number;
  flow(x: number, y: number, time?: number, options?: FieldOptions): number;
  worley(x: number, y: number, time?: number, options?: FieldOptions): number;
  voronoi(x: number, y: number, time?: number, options?: FieldOptions): number;
  plasma(x: number, y: number, time?: number, options?: FieldOptions): number;
  interference(x: number, y: number, time?: number, options?: FieldOptions): number;
  vortex(x: number, y: number, time?: number, options?: FieldOptions): number;
  metaballs(x: number, y: number, time?: number, options?: FieldOptions): number;
  caustics(x: number, y: number, time?: number, options?: FieldOptions): number;
  strata(x: number, y: number, time?: number, options?: FieldOptions): number;
  radar(x: number, y: number, time?: number, options?: FieldOptions): number;
  constellation(x: number, y: number, time?: number, options?: FieldOptions): number;
  liquid(x: number, y: number, time?: number, options?: FieldOptions): number;
  electric(x: number, y: number, time?: number, options?: FieldOptions): number;
  ripple(x: number, y: number, time?: number, options?: FieldOptions): number;
  kaleidoscope(x: number, y: number, time?: number, options?: FieldOptions): number;
}

export const fbm: FieldSampler;
export const ridged: FieldSampler;
export const domainWarp: FieldSampler;
export const curl: FieldSampler;
export const flow: FieldSampler;
export const worley: FieldSampler;
export const voronoi: FieldSampler;
export const plasma: FieldSampler;
export const interference: FieldSampler;
export const vortex: FieldSampler;
export const metaballs: FieldSampler;
export const caustics: FieldSampler;
export const strata: FieldSampler;
export const radar: FieldSampler;
export const constellation: FieldSampler;
export const liquid: FieldSampler;
export const electric: FieldSampler;
export const ripple: FieldSampler;
export const kaleidoscope: FieldSampler;
export const FIELDS: Readonly<Record<FieldId, FieldSampler>>;
export const FIELD_IDS: readonly FieldId[];
export const FIELD_ALIASES: Readonly<Record<FieldAlias, FieldId>>;
export const DEFAULT_FIELD_KIT: FieldKit;
export function createFieldKit(seed?: unknown): FieldKit;

export default FieldKit;
