import type { CacheHit } from '../events/cache/cache-hit';
import type { CacheMiss } from '../events/cache/cache-miss';
import type { CacheWritten } from '../events/cache/cache-written';
import type { CacheCleared } from '../events/cache/cache-cleared';
import type { CacheDeleted } from '../events/cache/cache-deleted';
import type { BusMessagePublished } from '../events/bus/bus-message-published';

/**
 * Shape of the emitter accepted by MasterCache
 * Should be compatible with node's EventEmitter and Emittery
 */
export interface Emitter {
  on: (event: string, callback: (...values: any[]) => void) => void
  once: (event: string, callback: (...values: any[]) => void) => void
  off: (event: string, callback: (...values: any[]) => void) => void
  emit: (event: string, ...values: any[]) => void
}

/**
 * Name/payload of the events emitted by the cache emitter
 */
export type CacheEvents = {
  'cache:cleared': ReturnType<CacheCleared['toJSON']>
  'cache:deleted': ReturnType<CacheDeleted['toJSON']>
  'cache:hit': ReturnType<CacheHit['toJSON']>
  'cache:miss': ReturnType<CacheMiss['toJSON']>
  'cache:written': ReturnType<CacheWritten['toJSON']>
  'bus:message:published': ReturnType<BusMessagePublished['toJSON']>
  'bus:message:received': ReturnType<BusMessagePublished['toJSON']>
}

/**
 * A cache event
 */
export interface CacheEvent {
  name: keyof CacheEvents
  toJSON: () => Record<string, any>
}
