import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

import 'package:mobdr/main.dart';
import 'package:mobdr/config/global_style.dart';

import 'package:super_tag_editor/tag_editor.dart';
import 'package:super_tag_editor/widgets/rich_text_widget.dart';

class PhotoTagPage extends StatefulWidget {
  // variables corresponding to the data parameters
  final int pp_id_distrib;
  final String pp_langage;
  final int pp_photoId;
  final List<String> pp_currentTags;

  // Requiring data parameters
  const PhotoTagPage({
    Key? key,
    required this.pp_id_distrib,
    required this.pp_langage,
    required this.pp_photoId,
    required this.pp_currentTags,
  }) : super(key: key);

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

class _PhotoTagPageState extends State<PhotoTagPage> {
  late List<String> allTagsList = [];
  late List<String> _selectedTags = [];
  bool isLoading = true;

  final FocusNode _focusNode = FocusNode();
  final TextEditingController _textEditingController = TextEditingController();
  bool focusTagEnabled = false;

  _onDelete(index) {
    setState(() {
      _selectedTags.removeAt(index);
    });
  }

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

    loadData().then((_) {
      setState(() {
        isLoading = false;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    if (isLoading) {
      return Center(child: CircularProgressIndicator());
    }
    return Scaffold(
      backgroundColor: Colors.white,
      appBar: AppBar(
          iconTheme: IconThemeData(
            color: GlobalStyle.appBarIconThemeColor,
          ),
          elevation: GlobalStyle.appBarElevation,
          title: Text(
            'Edit tags ...',
            style: GlobalStyle.appBarTitle,
          ),
          backgroundColor: GlobalStyle.appBarBackgroundColor,
          systemOverlayStyle: GlobalStyle.appBarSystemOverlayStyle),
      body: Center(
        child: Padding(
          padding: const EdgeInsets.all(16.0),
          child: ListView(
            children: <Widget>[
              TagEditor<String>(
                length: _selectedTags.length,
                controller: _textEditingController,
                focusNode: _focusNode,
                delimiters: [',', ' '],
                hasAddButton: true,
                resetTextOnSubmitted: true,
                // This is set to grey just to illustrate the `textStyle` prop
                textStyle: const TextStyle(color: Colors.grey),
                onSubmitted: (outstandingValue) {
                  setState(() {
                    _selectedTags.add(outstandingValue);
                  });
                },
                inputDecoration: const InputDecoration(
                  border: InputBorder.none,
                  hintText: 'Enter tag ...',
                ),
                onTagChanged: (newValue) {
                  setState(() {
                    _selectedTags.add(newValue);
                  });
                },
                tagBuilder: (context, index) => Container(
                  color: focusTagEnabled && index == _selectedTags.length - 1
                      ? Colors.redAccent
                      : Colors.white,
                  child: _Chip(
                    index: index,
                    label: _selectedTags[index],
                    onDeleted: _onDelete,
                  ),
                ),
                // InputFormatters example, this disallow \ and /
                inputFormatters: [
                  FilteringTextInputFormatter.deny(RegExp(r'[/\\]'))
                ],
                useDefaultHighlight: false,
                suggestionBuilder: (context, state, data, index, length,
                    highlight, suggestionValid) {
                  var borderRadius =
                      const BorderRadius.all(Radius.circular(20));
                  if (index == 0) {
                    borderRadius = const BorderRadius.only(
                      topLeft: Radius.circular(20),
                      topRight: Radius.circular(20),
                    );
                  } else if (index == length - 1) {
                    borderRadius = const BorderRadius.only(
                      bottomRight: Radius.circular(20),
                      bottomLeft: Radius.circular(20),
                    );
                  }
                  return InkWell(
                    onTap: () {
                      setState(() {
                        _selectedTags.add(data);
                      });
                      state.resetTextField();
                      state.closeSuggestionBox();
                    },
                    child: Container(
                        decoration: highlight
                            ? BoxDecoration(
                                color: Theme.of(context).focusColor,
                                borderRadius: borderRadius)
                            : null,
                        padding: const EdgeInsets.all(16),
                        child: RichTextWidget(
                          wordSearched: suggestionValid ?? '',
                          textOrigin: data,
                        )),
                  );
                },
                onFocusTagAction: (focused) {
                  setState(() {
                    focusTagEnabled = focused;
                  });
                },
                onDeleteTagAction: () {
                  if (_selectedTags.isNotEmpty) {
                    setState(() {
                      _selectedTags.removeLast();
                    });
                  }
                },
                onSelectOptionAction: (item) {
                  setState(() {
                    _selectedTags.add(item);
                  });
                },
                suggestionsBoxElevation: 10,
                findSuggestions: (String query) {
                  if (query.isNotEmpty) {
                    var lowercaseQuery = query.toLowerCase();
                    var filteredList = allTagsList
                        .where((tag) =>
                            !_selectedTags.contains(tag) &&
                            (tag.toLowerCase().startsWith(lowercaseQuery) ||
                                tag.toLowerCase().contains(lowercaseQuery)))
                        .toList(growable: false);

                    filteredList.sort((a, b) => a
                        .toLowerCase()
                        .indexOf(lowercaseQuery)
                        .compareTo(b.toLowerCase().indexOf(lowercaseQuery)));

                    return filteredList;
                  }
                  return [];
                },
              ),
              const Divider(),
              ElevatedButton(
                onPressed: () async {
                  // Save the selected tags to the database
                  await saveSelectedTags(
                      _selectedTags, widget.pp_id_distrib, widget.pp_langage);

                  Navigator.pop(
                      context, _selectedTags.map((tag) => tag).toList());
                },
                child: const Text('Save'),
              ),
            ],
          ),
        ),
      ),
    );
  }

  Future<void> loadData() async {
    allTagsList = await objectbox.getVisitTagsLabels(
        widget.pp_id_distrib, widget.pp_langage);
    _selectedTags = List<String>.from(widget.pp_currentTags);
  }

  /// Saves the selected tags for a photo to the ObjectBox database.
  ///
  /// Parameters:
  ///   tags: The list of tags to save.
  ///   distribId: The ID of the distribution associated with the photo.
  ///   langage: The language code for the tags.
  ///
  /// If the list of tags is empty, the function will exit without saving any tags.
  /// Otherwise, any new tags that are not already in the database will be added,
  /// and the photo's tags will be saved to the database.
  ///
  /// Returns:
  ///   Nothing.
  Future<void> saveSelectedTags(
      List<String> tags, int distribId, String langage) async {
    if (tags.isNotEmpty) {
      // determines if there are any new tags
      final newTags = tags.where((tag) => !allTagsList.contains(tag)).toList();

      for (final tag in newTags) {
        // insert new tag in the database
        objectbox.addVisitTag(0, distribId, tag, langage);
      }
    }

    // save photo tag in the database
    objectbox.putPhotoTags(widget.pp_photoId, tags);
  }
}

class _Chip extends StatelessWidget {
  const _Chip({
    required this.label,
    required this.onDeleted,
    required this.index,
  });

  final String label;
  final ValueChanged<int> onDeleted;
  final int index;

  @override
  Widget build(BuildContext context) {
    return Chip(
      labelPadding: const EdgeInsets.only(left: 8.0),
      label: Text(label),
      deleteIcon: const Icon(
        Icons.close,
        size: 18,
      ),
      onDeleted: () {
        onDeleted(index);
      },
    );
  }
}
