// lib/editor/input/tool_settings.dart
//
// Per-tool settings memory for the tool palette (F1/F5/F11). Each tool keeps its
// OWN color + width, so switching pen → highlighter → pen restores the pen's
// last color/width instead of bleeding the highlighter's. Immutable value type
// with copy-on-write updates; the toolbar holds one of these and persists it.
//
// Pure (no widgets/storage); fully unit-tested.

import 'package:flutter/foundation.dart';

enum EditorToolType { pen, highlighter, eraser }

/// Color (ARGB int) + width (fraction of page width) for one tool. The eraser
/// ignores color but keeps a width (its radius).
@immutable
class ToolConfig {
  const ToolConfig({required this.color, required this.width});

  final int color;
  final double width;

  ToolConfig copyWith({int? color, double? width}) =>
      ToolConfig(color: color ?? this.color, width: width ?? this.width);

  @override
  bool operator ==(Object other) =>
      other is ToolConfig && other.color == color && other.width == width;

  @override
  int get hashCode => Object.hash(color, width);
}

/// The active tool + each tool's remembered [ToolConfig].
@immutable
class ToolSettings {
  const ToolSettings({required this.active, required Map<EditorToolType, ToolConfig> configs})
      : _configs = configs;

  /// Sensible starting state: black thin pen, yellow fat highlighter, medium
  /// eraser; pen active.
  factory ToolSettings.defaults() => const ToolSettings(
        active: EditorToolType.pen,
        configs: {
          EditorToolType.pen: ToolConfig(color: 0xFF000000, width: 0.003),
          EditorToolType.highlighter:
              ToolConfig(color: 0x80FFEB3B, width: 0.02),
          EditorToolType.eraser: ToolConfig(color: 0x00000000, width: 0.02),
        },
      );

  final EditorToolType active;
  final Map<EditorToolType, ToolConfig> _configs;

  ToolConfig configFor(EditorToolType tool) =>
      _configs[tool] ?? const ToolConfig(color: 0xFF000000, width: 0.003);

  ToolConfig get activeConfig => configFor(active);

  /// Switch the active tool (each tool's own color/width is remembered).
  ToolSettings withActive(EditorToolType tool) =>
      ToolSettings(active: tool, configs: _configs);

  ToolSettings _withConfig(EditorToolType tool, ToolConfig config) {
    return ToolSettings(
      active: active,
      configs: {..._configs, tool: config},
    );
  }

  /// Set the ACTIVE tool's color (no-op semantics for the eraser are the
  /// caller's choice; the value is still stored).
  ToolSettings withColor(int color) =>
      _withConfig(active, activeConfig.copyWith(color: color));

  /// Set the ACTIVE tool's width.
  ToolSettings withWidth(double width) =>
      _withConfig(active, activeConfig.copyWith(width: width));

  @override
  bool operator ==(Object other) =>
      other is ToolSettings &&
      other.active == active &&
      mapEquals(other._configs, _configs);

  @override
  int get hashCode => Object.hash(active, Object.hashAll(_configs.entries));
}
