import 'dart:async';

import 'package:aitrainer_app/model/workout_menu_tree.dart';
import 'package:aitrainer_app/util/trans.dart';
import 'package:aitrainer_app/library/dropdown_search/dropdown_search.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';

class SearchBarStream {
  static final SearchBarStream _singleton = SearchBarStream._internal();
  final StreamController<bool> streamController = StreamController<bool>.broadcast();
  bool searching = false;

  Stream get stream => streamController.stream;
  StreamController getStreamController() => streamController;

  factory SearchBarStream() => _singleton;

  SearchBarStream._internal();

  void dispose() {
    streamController.close();
  }
}

// ignore: must_be_immutable
class MenuSearchBar extends StatelessWidget {
  final List<WorkoutMenuTree> listItems;
  final Function(WorkoutMenuTree) onFind;
  bool showIcon;
  MenuSearchBar({required this.listItems, required this.onFind, this.showIcon = true});

  @override
  Widget build(BuildContext context) {
    return AnimatedSearch(
      listItems: listItems,
      onFind: onFind,
      showIcon: showIcon,
    );
  }
}

// ignore: must_be_immutable
class AnimatedSearch extends StatefulWidget {
  final List<WorkoutMenuTree> listItems;
  final Function(WorkoutMenuTree) onFind;
  bool showIcon = true;

  AnimatedSearch({required this.listItems, required this.onFind, required this.showIcon});

  @override
  _AnimatedSearch createState() => _AnimatedSearch();
}

class _AnimatedSearch extends State<AnimatedSearch> {
  bool isSearching = false;
  final Stream stream = SearchBarStream().stream;
  var subscription;

  @override
  void initState() {
    super.initState();
  }

  @override
  void didChangeDependencies() {
    subscription = stream.listen((value) {
      setState(() {
        isSearching = SearchBarStream().searching;
      });
    });
    super.didChangeDependencies();
  }

  @override
  void dispose() {
    subscription.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Container(
        padding: EdgeInsets.only(top: 0),
        child: Stack(
          alignment: Alignment.center,
          children: [
            AnimateExpansion(
                animate: widget.showIcon ? !isSearching : false,
                axisAlignment: 1.0,
                child: IconButton(
                  onPressed: () => {
                    setState(() {
                      isSearching = !isSearching;
                      SearchBarStream().searching = isSearching;
                      SearchBarStream().getStreamController().add(true);
                    })
                  },
                  icon: Icon(
                    Icons.search,
                    color: Color(0xffb4f500),
                    size: 40,
                  ),
                )),
            AnimateExpansion(
              animate: widget.showIcon ? isSearching : true,
              axisAlignment: -1.0,
              child: Search(
                listItems: widget.listItems,
                onFind: widget.onFind,
              ),
            ),
          ],
        ));
  }
}

// ignore: must_be_immutable
class Search extends StatelessWidget with Trans {
  final List<WorkoutMenuTree> listItems;
  final Function(WorkoutMenuTree) onFind;

  Search({required this.listItems, required this.onFind});

  @override
  Widget build(BuildContext context) {
    setContext(context);
    return SizedBox(
      width: MediaQuery.of(context).size.width * .6,
      child: DropdownSearch<WorkoutMenuTree>(
          onPopupDismissed: () => {SearchBarStream().searching = false, SearchBarStream().getStreamController().add(false)},
          showAsSuffixIcons: false,
          showSearchBox: true,
          mode: Mode.DIALOG,
          showSelectedItem: false,
          items: listItems,
          onChanged: (value) => onFind(value),
          dropdownSearchDecoration: InputDecoration(
            contentPadding: EdgeInsets.only(left: 15, top: 0, bottom: 5),
            labelStyle: GoogleFonts.inter(fontSize: 12, color: Colors.yellow[50]),
            fillColor: Colors.black38,
            filled: true,
            border: OutlineInputBorder(
              gapPadding: 8.0,
              borderRadius: BorderRadius.circular(12.0),
              borderSide: BorderSide(color: Colors.white12, width: 0.4),
            ),
          ),
          searchBoxController: TextEditingController(),
          searchBoxDecoration: InputDecoration(
            contentPadding: EdgeInsets.only(left: 15, top: 5, bottom: 5),
            labelText: t("Search Exercises..."),
            labelStyle: GoogleFonts.inter(fontSize: 12, color: Colors.grey[400]),
            fillColor: Colors.white24,
            filled: true,
            border: OutlineInputBorder(
              gapPadding: 8.0,
              borderRadius: BorderRadius.circular(12.0),
              borderSide: BorderSide(color: Colors.white12, width: 0.4),
            ),
          ),
          popupBackgroundColor: Colors.grey[700],
          popupItemBuilder: (context, item, isSelected) {
            return Container(
              margin: EdgeInsets.all(3),
              decoration: BoxDecoration(
                image: DecorationImage(
                  image: AssetImage('asset/image/WT_black_G_background.jpg'),
                  fit: BoxFit.cover,
                ),
              ),
              child: ListTile(
                selected: isSelected,
                title: Text(
                  item.name,
                  style: GoogleFonts.inter(color: Colors.yellow[300], fontSize: 16),
                ),
                subtitle: Text(
                  item.parentName,
                  maxLines: 1,
                  style: GoogleFonts.inter(color: Colors.grey[400]),
                ),
                leading: ClipRRect(
                  borderRadius: BorderRadius.circular(8.0),
                  child: Image.asset(item.imageName),
                ),
              ),
            );
          },
          emptyBuilder: (context, searchEntry) => Center(
                  child: Text(
                t("No exercise found"),
                textAlign: TextAlign.center,
                style: GoogleFonts.inter(color: Colors.yellow[200], fontSize: 16),
              )),
          dropdownBuilder: (context, WorkoutMenuTree? item, itemDesignation) => Container(
                  child: ListView(scrollDirection: Axis.vertical, shrinkWrap: true, children: [
                (item == null)
                    ? Container(
                        height: 15,
                        padding: EdgeInsets.all(0),
                        child: Text(
                          t("Search Exercises..."),
                          style: GoogleFonts.inter(color: Colors.grey[400], fontSize: 14),
                        ),
                      )
                    : Container(
                        height: 15,
                        padding: EdgeInsets.all(0),
                        child: Text(
                          item.name,
                          maxLines: 3,
                          style: GoogleFonts.inter(color: Colors.yellow[400], fontSize: 14),
                        ),
                      ),
              ]))),
    );
  }
}

class AnimateExpansion extends StatefulWidget {
  final Widget child;
  final bool animate;
  final double axisAlignment;
  AnimateExpansion({
    this.animate = false,
    required this.axisAlignment,
    required this.child,
  });

  @override
  _AnimateExpansionState createState() => _AnimateExpansionState();
}

class _AnimateExpansionState extends State<AnimateExpansion> with SingleTickerProviderStateMixin {
  late AnimationController _animationController;
  late Animation<double> _animation;

  void prepareAnimations() {
    _animationController = AnimationController(
      vsync: this,
      duration: Duration(milliseconds: 350),
    );
    _animation = CurvedAnimation(
      parent: _animationController,
      curve: Curves.easeInCubic,
      reverseCurve: Curves.easeOutCubic,
    );
  }

  void _toggle() {
    if (widget.animate) {
      _animationController.forward();
    } else {
      _animationController.reverse();
    }
  }

  @override
  void initState() {
    super.initState();
    prepareAnimations();
    _toggle();
  }

  @override
  void didUpdateWidget(AnimateExpansion oldWidget) {
    super.didUpdateWidget(oldWidget);
    _toggle();
  }

  @override
  Widget build(BuildContext context) {
    return SizeTransition(axis: Axis.horizontal, axisAlignment: -1.0, sizeFactor: _animation, child: widget.child);
  }

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