import 'package:comunic/helpers/groups_helper.dart';
import 'package:comunic/helpers/search_helper.dart';
import 'package:comunic/helpers/users_helper.dart';
import 'package:comunic/lists/groups_list.dart';
import 'package:comunic/lists/search_results_list.dart';
import 'package:comunic/lists/users_list.dart';
import 'package:comunic/models/search_result.dart';
import 'package:comunic/ui/routes/main_route/main_route.dart';
import 'package:comunic/ui/widgets/account_image_widget.dart';
import 'package:comunic/ui/widgets/group_icon_widget.dart';
import 'package:comunic/utils/intl_utils.dart';
import 'package:comunic/utils/ui_utils.dart';
import 'package:flutter/material.dart';

/// Global search field
///
/// @author Pierre Hubert

const _MainSearchColor = Color(0xFF999990);

class _SearchResults {
  final SearchResultsList list;
  final UsersList users;
  final GroupsList groups;

  _SearchResults(this.list, this.users, this.groups);
}

class GlobalSearchField extends StatefulWidget {
  @override
  _GlobalSearchFieldState createState() => _GlobalSearchFieldState();
}

class _GlobalSearchFieldState extends State<GlobalSearchField> {
  final _focusNode = FocusNode();

  final _controller = TextEditingController();

  _SearchResults _searchResultsList;

  OverlayEntry _overlayEntry;

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

    _focusNode.addListener(() {
      if (!_focusNode.hasFocus) _removeOverlay();
    });
  }

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: Material(
        color: Color(0xFF374850),
        borderRadius: BorderRadius.all(Radius.circular(5.0)),
        child: Padding(
          padding: const EdgeInsets.only(left: 8.0),
          child: TextField(
            autofocus: false,
            controller: _controller,
            focusNode: _focusNode,
            textAlignVertical: TextAlignVertical.center,
            onChanged: (s) => _refreshSearch(),
            decoration: InputDecoration(
              hintText: tr("Search..."),
              hintStyle: TextStyle(color: _MainSearchColor),
              suffixIcon: Icon(
                Icons.search,
                color: _MainSearchColor,
              ),
              focusedBorder: InputBorder.none,
              border: InputBorder.none,
              alignLabelWithHint: false,
            ),
          ),
        ),
      ),
    );
  }

  void _refreshSearch() async {
    if (_controller.text.length < 1) {
      _removeOverlay();
      return;
    }

    _showOverlay();

    try {
      final results = await SearchHelper().globalSearch(_controller.text);
      final users = await UsersHelper().getListWithThrow(results.usersId);
      final groups = await GroupsHelper().getListOrThrow(results.groupsId);

      _searchResultsList = _SearchResults(results, users, groups);

      if (_overlayEntry != null) _overlayEntry.markNeedsBuild();
    } catch (e, s) {
      print("Could not perform search! $e\n$s");
      showSimpleSnack(context, tr("Could not perform search!"));
    }
  }

  void _showOverlay() {
    if (_overlayEntry == null) {
      _overlayEntry = _createOverlayEntry();
      Overlay.of(context).insert(_overlayEntry);
    }
  }

  void _removeOverlay() {
    if (_overlayEntry != null) {
      _overlayEntry.remove();
      _overlayEntry = null;
    }
  }

  OverlayEntry _createOverlayEntry() {
    RenderBox renderBox = context.findRenderObject();
    var size = renderBox.size;
    var offset = renderBox.localToGlobal(Offset.zero);

    return OverlayEntry(
        builder: (context) => Positioned(
              left: offset.dx,
              top: offset.dy + size.height + 5.0,
              width: size.width,
              height: 300,
              child: Material(
                elevation: 4.0,
                child: _SearchResultsWidget(
                  results: _searchResultsList,
                  onTap: _removeOverlay,
                ),
              ),
            ));
  }
}

class _SearchResultsWidget extends StatelessWidget {
  final _SearchResults results;
  final Function() onTap;

  const _SearchResultsWidget({
    Key key,
    @required this.results,
    @required this.onTap,
  })  : assert(onTap != null),
        super(key: key);

  @override
  Widget build(BuildContext context) {
    if (results == null) return Container();
    return ListView.builder(
      itemBuilder: _builder,
      itemCount: results.list.length,
    );
  }

  Widget _builder(BuildContext context, int index) {
    final res = results.list[index];

    switch (res.kind) {
      case SearchResultKind.USER:
        final user = results.users.getUser(res.id);
        return ListTile(
          leading: AccountImageWidget(user: user),
          title: Text(user.displayName),
          onTap: () {
            MainController.of(context).openUserPage(user.id);
            onTap();
          },
        );

      case SearchResultKind.GROUP:
        final group = results.groups.getGroup(res.id);
        return ListTile(
          leading: GroupIcon(group: group),
          title: Text(group.displayName),
          onTap: () {
            MainController.of(context).openGroup(group.id);
            onTap();
          },
        );
    }
    throw Exception("Unreachable statement!");
  }
}