import 'package:aves/model/entry/entry.dart';
import 'package:aves/model/viewer/view_state.dart';
import 'package:aves/widgets/viewer/view/controller.dart';
import 'package:aves_magnifier/aves_magnifier.dart';
import 'package:collection/collection.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart';
import 'package:leak_tracker/leak_tracker.dart';

class ViewStateConductor {
  final List<ViewStateController> _controllers = [];
  Size _viewportSize = Size.zero;

  static const maxControllerCount = 3;

  ViewStateConductor() {
    if (kFlutterMemoryAllocationsEnabled) {
      LeakTracking.dispatchObjectCreated(
        library: 'aves',
        className: '$ViewStateConductor',
        object: this,
      );
    }
  }

  Future<void> dispose() async {
    if (kFlutterMemoryAllocationsEnabled) {
      LeakTracking.dispatchObjectDisposed(object: this);
    }
    _controllers.forEach((v) => v.dispose());
    _controllers.clear();
  }

  set viewportSize(Size size) => _viewportSize = size;

  ViewStateController getOrCreateController(AvesEntry entry) {
    // Identificazione robusta anche per remoti (uri può essere null):
    // usa SEMPRE (id, pageId) come chiave logica del controller.
    var controller = getController(entry);
    if (controller != null) {
      _controllers.remove(controller);
    } else {
      // inizializza lo stato per combaciare lo stato iniziale del magnifier
      const initialScale = ScaleLevel(ref: ScaleReference.contained);
      final initialValue = ViewState(
        position: Offset.zero,
        scale: ScaleBoundaries(
          allowOriginalScaleBeyondRange: true,
          minScale: initialScale,
          maxScale: initialScale,
          initialScale: initialScale,
          viewportSize: _viewportSize,
          contentSize: entry.displaySize,
        ).initialScale,
        viewportSize: _viewportSize,
        contentSize: entry.displaySize,
      );
      controller = ViewStateController(
        entry: entry,
        viewStateNotifier: ValueNotifier<ViewState>(initialValue),
      );
    }
    _controllers.insert(0, controller);
    while (_controllers.length > maxControllerCount) {
      _controllers.removeLast().dispose();
    }
    return controller;
  }

  ViewStateController? getController(AvesEntry entry) {
    // Confronto per (id, pageId) invece di (uri, pageId)
    return _controllers.firstWhereOrNull(
      (c) => c.entry.id == entry.id && c.entry.pageId == entry.pageId,
    );
  }

  void reset(AvesEntry entry) {
    // Reset per id (gli uri remoti possono essere null, quindi non affidabili)
    final ids = <int>{
      entry.id,
      ...?entry.stackedEntries?.map((e) => e.id),
    };
    final entryControllers = _controllers.where((v) => ids.contains(v.entry.id)).toSet();
    entryControllers.forEach((controller) {
      _controllers.remove(controller);
      controller.dispose();
    });
  }
}
