Source: fx/FlashEffect.js

// src/engine/fx/FlashEffect.js
import BaseEffect from './BaseEffect.js'

/**
 * @class FlashEffect
 * @extends BaseEffect
 * @description Creates a screen flash visual effect with a specified color and opacity.
 */
class FlashEffect extends BaseEffect {
  /**
   * Creates an instance of FlashEffect.
   * @param {object} options - Configuration options for the flash effect.
   * @param {string} [options.color='rgba(255, 255, 255, 0.5)'] - The color of the flash (CSS color string).
   * @param {number} [options.duration=300] - Duration of the flash in milliseconds.
   * @param {number} [options.maxOpacity=0.7] - The peak opacity of the flash (0 to 1).
   * @param {boolean} [options.fadeOut=true] - Whether the flash opacity should fade out over its duration.
   * @param {boolean} [options.startsActive=true] - Whether the effect starts active.
   * @param {import('../core/IroncladEngine.js').default} [options.engine=null] - Optional reference to the engine.
   * @param {string} [options.id] - Optional ID for logging/identification.
   */
  constructor(options = {}) {
    const effectId =
      options.id || `FlashEffect(C:${options.color || 'white'},D:${options.duration || 300})`
    super({ ...options, id: effectId }) // Handles duration, startsActive, engine, id

    this.color = options.color || 'rgba(255, 255, 255, 0.5)' // Default to semi-transparent white
    this.maxOpacity = Math.max(
      0,
      Math.min(options.maxOpacity !== undefined ? options.maxOpacity : 0.7, 1),
    )
    this.fadeOut = options.fadeOut !== undefined ? options.fadeOut : true

    this.currentOpacity = 0 // Will be set by start() or if startsActive

    if (this.isActive) {
      // If startsActive was true in BaseEffect
      this.currentOpacity = this.maxOpacity
      // Timer and isFinished are handled by BaseEffect's constructor or start()
    }
    // console.log(`[${this.id} Constructor] Color: ${this.color}, MaxOpacity: ${this.maxOpacity}, FadeOut: ${this.fadeOut}, Active: ${this.isActive}`);
  }

  /**
   * Updates the flash effect's opacity over time if fadeOut is enabled.
   * @param {number} deltaTime - The time elapsed since the last frame, in seconds.
   */
  update(deltaTime) {
    if (!this.isActive || this.isFinished) {
      if (this.currentOpacity !== 0) this.currentOpacity = 0
      return
    }

    super.update(deltaTime) // Handles timer and sets isFinished, isActive

    if (this.isFinished) {
      // If super.update() just marked it as finished
      this.currentOpacity = 0
    } else if (this.fadeOut && this.duration > 0) {
      // Linear fade out
      this.currentOpacity =
        this.maxOpacity * Math.max(0, (this.duration - this.timer) / this.duration)
    } else if (!this.fadeOut) {
      // If no fadeOut, opacity remains maxOpacity until finished, then drops to 0
      this.currentOpacity = this.isFinished ? 0 : this.maxOpacity
    }
    this.currentOpacity = Math.max(0, Math.min(this.currentOpacity, this.maxOpacity)) // Clamp

    // console.log(`[${this.id} Update] Timer: ${this.timer.toFixed(0)}, CurrentOpacity: ${this.currentOpacity.toFixed(2)}, Active: ${this.isActive}, Finished: ${this.isFinished}`);
  }

  /**
   * Applies the screen flash by drawing a colored overlay.
   * This method is called by the EffectsManager during its postRender phase,
   * typically after the scene and any positional effects have been drawn.
   * @param {CanvasRenderingContext2D} mainContext - The context of the main (visible) canvas.
   * @param {HTMLCanvasElement} sceneCanvas - The offscreen canvas (not directly used by flash, but passed by manager).
   * @param {object} [effectPipelineData={}] - Data from previous effects (not typically used by flash).
   * @returns {void}
   */
  apply(mainContext, sceneCanvas, effectPipelineData = {}) {
    if (!this.isActive || this.isFinished || this.currentOpacity <= 0) {
      // console.log(`[${this.id} Apply] Not active or zero opacity. Opacity: ${this.currentOpacity}, Active: ${this.isActive}`);
      return
    }

    const originalAlpha = mainContext.globalAlpha
    mainContext.globalAlpha = this.currentOpacity
    mainContext.fillStyle = this.color
    mainContext.fillRect(0, 0, mainContext.canvas.width, mainContext.canvas.height)
    mainContext.globalAlpha = originalAlpha // Restore globalAlpha

    // console.log(`[${this.id} Apply] Applied flash. Color: ${this.color}, Opacity: ${this.currentOpacity.toFixed(2)}`);
  }

  /**
   * Starts or restarts the flash effect.
   */
  start() {
    super.start() // Resets timer, sets isActive=true, isFinished=false
    this.currentOpacity = this.maxOpacity
    // console.log(`[${this.id} Start] Flash started/restarted. Opacity: ${this.currentOpacity}`);
  }

  /**
   * Resets the flash effect to its initial state.
   */
  reset() {
    super.reset() // Resets timer, isActive, isFinished
    this.currentOpacity = 0 // Opacity is 0 until started
    // console.log(`[${this.id} Reset] Flash reset.`);
  }
}

export default FlashEffect