// Double-buffer helper on top of [PageTileCache] to kill zoom white-flash:
// keep painting the last good tile while a higher-DPI raster is in flight.

import 'dart:ui' as ui;

import 'package:flutter/widgets.dart';

import 'page_tile_cache.dart';

/// Holds the "last good" page image for the currently visible page so a zoom
/// settle never exposes an empty frame (plan W2 / R11).
class PageTileLayer extends ChangeNotifier {
  PageTileLayer({PageTileCache? cache}) : _cache = cache ?? PageTileCache();

  final PageTileCache _cache;
  ui.Image? _lastGood;
  TileKey? _lastKey;

  PageTileCache get cache => _cache;
  ui.Image? get lastGood => _lastGood;
  TileKey? get lastKey => _lastKey;

  /// Snap continuous zoom to a coarse DPI bucket (avoids a tile per frame).
  static int dpiBucketFor(double zoom, {double baseDpi = 96, double step = 0.5}) {
    final raw = zoom / step;
    final snapped = raw.round().clamp(1, 16);
    return (snapped * step * baseDpi).round();
  }

  /// Promote [image] as the last-good tile for [key].
  void put(TileKey key, ui.Image image) {
    _cache.put(key, image);
    _lastGood = image;
    _lastKey = key;
    notifyListeners();
  }

  /// Prefer exact bucket; else fall back to last-good so zoom never blanks.
  ui.Image? resolve(TileKey key) {
    final hit = _cache.get(key);
    if (hit != null) {
      _lastGood = hit;
      _lastKey = key;
      return hit;
    }
    return _lastGood;
  }

  void clear() {
    _lastGood = null;
    _lastKey = null;
    _cache.dispose();
    notifyListeners();
  }

  @override
  void dispose() {
    clear();
    super.dispose();
  }
}
