import 'dart:async';

import 'package:flutter/material.dart';
import 'package:sendtrain/services/functional/debouncer.dart';
import 'package:sendtrain/widgets/generic/elements/form_text_input.dart';

class Suggestion<T> {
  T content;

  Suggestion(this.content);

  Widget resultWidget() {
    return ListTile(
      title: Text('test'),
    );
  }
}

// controller: manages the selected content
// service: manages the requests for the specific data to search against
// title: the title of the text input
// callback: the fuction called when a selection is made
class FormSearchInput extends StatefulWidget {
  const FormSearchInput(
      {super.key,
      required this.controller,
      required this.service,
      required this.resultHandler,
      this.title});

  final String? title;
  final TextEditingController controller;
  final dynamic service;
  final Function resultHandler;

  @override
  State<FormSearchInput> createState() => _FormSearchInputState();
}

class _FormSearchInputState extends State<FormSearchInput> {
  String? _currentQuery;

  late final service = widget.service;
  late final resultHandler = widget.resultHandler;
  // The most recent suggestions received from the API.
  late Iterable<Widget> _lastOptions = <Widget>[];
  late final Debouncer debouncer;

  // @override
  // initState() {
  //   service = widget.service;
  // }

  // Calls the "remote" API to search with the given query. Returns null when
  // the call has been made obsolete.
  Future<Iterable<Suggestion>?> _search(String query) async {
    _currentQuery = query;

    // In a real application, there should be some error handling here.
    if (query.isNotEmpty && query.length > 3) {
      final List<Suggestion>? suggestions =
          await service.fetchSuggestions(_currentQuery!);

      // If another search happened after this one, throw away these options.
      if (_currentQuery != query) {
        return null;
      }
      _currentQuery = null;

      return suggestions?.map((suggestion) => suggestion);
    } else {
      return null;
    }
  }

  @override
  void initState() {
    super.initState();
    debouncer = Debouncer(Duration(milliseconds: 50), _search);
  }

  @override
  Widget build(BuildContext context) {
    return SearchAnchor(
        isFullScreen: false,
        builder: (BuildContext context, SearchController controller) {
          return FormTextInput(
              controller: widget.controller,
              title: widget.title ?? "",
              icon: Icon(Icons.search_rounded),
              maxLines: 2,
              requiresValidation: false,
              onTap: () {
                controller.openView();
              });
        },
        suggestionsBuilder:
            (BuildContext context, SearchController controller) async {
          final List<Suggestion>? options =
              (await debouncer.process(controller.text))?.toList();
          if (options == null) {
            return _lastOptions;
          }
          _lastOptions = List<ListTile>.generate(options.length, (int index) {
            final Suggestion item = options[index];
            final dynamic content = item.content;
            return service.resultWidget(content, () {
              resultHandler(content, service);
              controller.closeView(null);
            });
          });

          return _lastOptions;
        });
  }
}
