export type EffectToolType =
  | 'none'
  | 'fog'
  | 'fire'
  | 'rain'
  | 'water'
  | 'darkness'
  | 'lightning'
  | 'sunbeam'
  | 'poisonCloud'
  | 'explosion'
  | 'freeze'
  | 'exploreBrush'
  | 'closeBrush'
  | 'eraser';

export type EffectInstanceType =
  | 'fog'
  | 'fire'
  | 'rain'
  | 'water'
  | 'darkness'
  | 'lightning'
  | 'sunbeam'
  | 'poisonCloud'
  | 'explosion'
  | 'freeze'
  | 'scorch'
  | 'ice'
  | 'shadow';

/** Нормализованные координаты (0..1) относительно области предпросмотра/презентации. */
export type NPoint = { x: number; y: number; tMs: number; pressure?: number };

export type EffectInstanceBase = {
  id: string;
  type: EffectInstanceType;
  /** Для детерминизма процедурных эффектов. */
  seed: number;
  /** Время создания по часам main-процесса. */
  createdAtMs: number;
};

export type FogInstance = EffectInstanceBase & {
  type: 'fog';
  points: NPoint[];
  radiusN: number;
  opacity: number;
  lifetimeMs: number | null;
};

export type FireInstance = EffectInstanceBase & {
  type: 'fire';
  points: NPoint[];
  radiusN: number;
  opacity: number;
  lifetimeMs: number | null;
};

export type RainInstance = EffectInstanceBase & {
  type: 'rain';
  points: NPoint[];
  radiusN: number;
  opacity: number;
  lifetimeMs: number | null;
};

export type WaterInstance = EffectInstanceBase & {
  type: 'water';
  points: NPoint[];
  radiusN: number;
  opacity: number;
  lifetimeMs: number | null;
};

export type DarknessInstance = EffectInstanceBase & {
  type: 'darkness';
  at: { x: number; y: number };
  intensity: number;
  lifetimeMs: number;
};

export type LightningInstance = EffectInstanceBase & {
  type: 'lightning';
  start: { x: number; y: number };
  end: { x: number; y: number };
  widthN: number;
  intensity: number;
  lifetimeMs: number;
};

/** Прямой луч сверху к точке удара (как у молнии геометрия штриха, другой визуал). */
export type SunbeamInstance = EffectInstanceBase & {
  type: 'sunbeam';
  start: { x: number; y: number };
  end: { x: number; y: number };
  widthN: number;
  intensity: number;
  lifetimeMs: number;
};

/** «Облако яда» — ядерный гриб в точке удара. */
export type PoisonCloudInstance = EffectInstanceBase & {
  type: 'poisonCloud';
  at: { x: number; y: number };
  radiusN: number;
  intensity: number;
  lifetimeMs: number;
};

/** «Взрыв» — one-shot webm в точке удара (тот же ассет, что у ловушки). */
export type ExplosionInstance = EffectInstanceBase & {
  type: 'explosion';
  at: { x: number; y: number };
  radiusN: number;
  intensity: number;
  lifetimeMs: number;
};

export type FreezeInstance = EffectInstanceBase & {
  type: 'freeze';
  at: { x: number; y: number };
  intensity: number;
  lifetimeMs: number;
};

export type ScorchInstance = EffectInstanceBase & {
  /** Внутренний инстанс: след после молнии. */
  type: 'scorch';
  at: { x: number; y: number };
  radiusN: number;
  opacity: number;
  lifetimeMs: number;
};

export type IceInstance = EffectInstanceBase & {
  /** Внутренний инстанс: ледяной след после заморозки. */
  type: 'ice';
  at: { x: number; y: number };
  radiusN: number;
  opacity: number;
  /** `null` — пятно не истекает по времени (снимается только «очистить» или ластик). */
  lifetimeMs: number | null;
};

export type ShadowInstance = EffectInstanceBase & {
  /** Внутренний инстанс: тёмное пятно после эффекта «Тьма». */
  type: 'shadow';
  at: { x: number; y: number };
  radiusN: number;
  opacity: number;
  lifetimeMs: number | null;
};

export type EffectInstance =
  | FogInstance
  | FireInstance
  | RainInstance
  | WaterInstance
  | DarknessInstance
  | LightningInstance
  | SunbeamInstance
  | PoisonCloudInstance
  | ExplosionInstance
  | FreezeInstance
  | ScorchInstance
  | IceInstance
  | ShadowInstance;

export type EffectToolState = {
  tool: EffectToolType;
  radiusN: number;
  intensity: number;
};

export type EffectsState = {
  revision: number;
  /** Текущее время по часам main-процесса (для синхронной анимации между окнами). */
  serverNowMs: number;
  tool: EffectToolState;
  instances: EffectInstance[];
};

export type EffectsEvent =
  | { kind: 'tool.set'; tool: EffectToolState }
  | { kind: 'instances.clear' }
  | { kind: 'instance.add'; instance: EffectInstance }
  | { kind: 'instance.remove'; id: string }
  | {
      kind: 'field.erase';
      points: NPoint[];
      radiusN: number;
      /** Если задано — стираются только эти типы полевых эффектов. */
      types?: readonly ('fog' | 'fire' | 'rain' | 'water')[];
      /**
       * `inclusive` (по умолчанию) — ластик: radius кисти + radius эффекта.
       * `brush` — гашение огня водой/дождём: только radius кисти.
       */
      hitMode?: 'inclusive' | 'brush';
    };
