import 'package:aves/model/entry/entry.dart';
import 'package:aves/model/source/collection_lens.dart';
import 'package:aves/theme/durations.dart';
import 'package:aves/utils/debouncer.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:aves/widgets/common/identity/empty.dart';
import 'package:aves/widgets/common/thumbnail/scroller.dart';
import 'package:aves/widgets/map/info_row.dart';
import 'package:aves/widgets/viewer/hero.dart';
import 'package:flutter/material.dart';

class MapEntryScroller extends StatefulWidget {
  final ValueNotifier<CollectionLens?> regionCollectionNotifier;
  final ValueNotifier<AvesEntry?> dotEntryNotifier;
  final ValueNotifier<int?> selectedIndexNotifier;
  final void Function(int index) onTap;

  const MapEntryScroller({
    super.key,
    required this.regionCollectionNotifier,
    required this.dotEntryNotifier,
    required this.selectedIndexNotifier,
    required this.onTap,
  });

  @override
  State<MapEntryScroller> createState() => _MapEntryScrollerState();
}

class _MapEntryScrollerState extends State<MapEntryScroller> {
  final ValueNotifier<AvesEntry?> _infoEntryNotifier = ValueNotifier(null);
  final Debouncer _infoDebouncer = Debouncer(delay: ADurations.mapInfoDebounceDelay);

  @override
  void initState() {
    super.initState();
    _registerWidget(widget);
    WidgetsBinding.instance.addPostFrameCallback((_) => _onSelectedEntryChanged());
  }

  @override
  void didUpdateWidget(covariant MapEntryScroller oldWidget) {
    super.didUpdateWidget(oldWidget);
    _unregisterWidget(oldWidget);
    _registerWidget(widget);
  }

  @override
  void dispose() {
    _unregisterWidget(widget);
    super.dispose();
  }

  void _registerWidget(MapEntryScroller widget) {
    widget.dotEntryNotifier.addListener(_onSelectedEntryChanged);
  }

  void _unregisterWidget(MapEntryScroller widget) {
    widget.dotEntryNotifier.removeListener(_onSelectedEntryChanged);
  }

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            SafeArea(
              top: false,
              bottom: false,
              child: MapInfoRow(entryNotifier: _infoEntryNotifier),
            ),
            const SizedBox(height: 8),
            ValueListenableBuilder<CollectionLens?>(
              valueListenable: widget.regionCollectionNotifier,
              builder: (context, regionCollection, child) {
                return AnimatedBuilder(
                  // update when entries are added/removed
                  animation: regionCollection ?? ChangeNotifier(),
                  builder: (context, child) {
                    final regionEntries = regionCollection?.sortedEntries ?? [];
                    return ThumbnailScroller(
                      availableWidth: MediaQuery.sizeOf(context).width,
                      entryCount: regionEntries.length,
                      entryBuilder: (index) => index < regionEntries.length ? regionEntries[index] : null,
                      indexNotifier: widget.selectedIndexNotifier,
                      onTap: widget.onTap,
                      heroTagger: (entry) => EntryHeroInfo(regionCollection, entry).tag,
                      highlightable: true,
                      showLocation: false,
                    );
                  },
                );
              },
            ),
          ],
        ),
        Positioned.fill(
          child: ValueListenableBuilder<AvesEntry?>(
            valueListenable: _infoEntryNotifier,
            builder: (context, infoEntry, child) {
              return ValueListenableBuilder<CollectionLens?>(
                valueListenable: widget.regionCollectionNotifier,
                builder: (context, regionCollection, child) {
                  return infoEntry == null && regionCollection != null && regionCollection.isEmpty
                      ? EmptyContent(
                          text: context.l10n.mapEmptyRegion,
                          alignment: Alignment.center,
                          fontSize: 18,
                        )
                      : const SizedBox();
                },
              );
            },
          ),
        ),
      ],
    );
  }

  void _onSelectedEntryChanged() {
    final selectedEntry = widget.dotEntryNotifier.value;
    if (_infoEntryNotifier.value == null || selectedEntry == null) {
      _infoEntryNotifier.value = selectedEntry;
    } else {
      _infoDebouncer(() => _infoEntryNotifier.value = selectedEntry);
    }
  }
}
