content: /*
   *  This file is part of BlackHole (https://github.com/Sangwan5688/BlackHole).
   * 
   * BlackHole is free software: you can redistribute it and/or modify
   * it under the terms of the GNU Lesser General Public License as published by
   * the Free Software Foundation, either version 3 of the License, or
   * (at your option) any later version.
   *
   * BlackHole is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
   * GNU Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public License
   * along with BlackHole.  If not, see <http://www.gnu.org/licenses/>.
   * 
   * Copyright (c) 2021-2022, Ankit Sangwan
   */
  
  import 'package:blackhole/CustomWidgets/collage.dart';
  import 'package:blackhole/CustomWidgets/gradient_containers.dart';
  import 'package:blackhole/CustomWidgets/miniplayer.dart';
  import 'package:blackhole/CustomWidgets/snackbar.dart';
  import 'package:blackhole/CustomWidgets/textinput_dialog.dart';
  import 'package:blackhole/Helpers/import_export_playlist.dart';
  import 'package:blackhole/Screens/Library/import.dart';
  import 'package:blackhole/Screens/Library/liked.dart';
  import 'package:flutter/material.dart';
  import 'package:flutter_gen/gen_l10n/app_localizations.dart';
  import 'package:hive_flutter/hive_flutter.dart';
  import 'package:logging/logging.dart';
  import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
  
  class PlaylistScreen extends StatefulWidget {
    @override
    _PlaylistScreenState createState() => _PlaylistScreenState();
  }
  
  class _PlaylistScreenState extends State<PlaylistScreen> {
    final Box settingsBox = Hive.box('settings');
    final List playlistNames =
        Hive.box('settings').get('playlistNames')?.toList() as List? ??
            ['Favorite Songs'];
    Map playlistDetails =
        Hive.box('settings').get('playlistDetails', defaultValue: {}) as Map;
    @override
    Widget build(BuildContext context) {
      if (!playlistNames.contains('Favorite Songs')) {
        playlistNames.insert(0, 'Favorite Songs');
        settingsBox.put('playlistNames', playlistNames);
      }
  
      return GradientContainer(
        child: Column(
          children: [
            Expanded(
              child: Scaffold(
                backgroundColor: Colors.transparent,
                appBar: AppBar(
                  title: Text(
                    AppLocalizations.of(context)!.playlists,
                  ),
                  centerTitle: true,
                  backgroundColor: Theme.of(context).brightness == Brightness.dark
                      ? Colors.transparent
                      : Theme.of(context).colorScheme.secondary,
                  elevation: 0,
                ),
                body: SingleChildScrollView(
                  physics: const BouncingScrollPhysics(),
                  child: Column(
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      const SizedBox(height: 5),
                      ListTile(
                        title: Text(AppLocalizations.of(context)!.createPlaylist),
                        leading: SizedBox.square(
                          dimension: 50,
                          child: Center(
                            child: Icon(
                              Icons.add_rounded,
                              color: Theme.of(context).iconTheme.color,
                            ),
                          ),
                        ),
                        onTap: () async {
                          await showTextInputDialog(
                            context: context,
                            title:
                                AppLocalizations.of(context)!.createNewPlaylist,
                            initialText: '',
                            keyboardType: TextInputType.name,
                            onSubmitted: (String value) async {
                              final RegExp avoid = RegExp(r'[\.\\\*\:\"\?#/;\|]');
                              value.replaceAll(avoid, '').replaceAll('  ', ' ');
                              if (value.trim() == '') {
                                value = 'Playlist ${playlistNames.length}';
                              }
                              while (playlistNames.contains(value) ||
                                  await Hive.boxExists(value)) {
                                // ignore: use_string_buffers
                                value = '$value (1)';
                              }
                              playlistNames.add(value);
                              settingsBox.put('playlistNames', playlistNames);
                              Navigator.pop(context);
                            },
                          );
                        },
                      ),
                      ListTile(
                        title: Text(AppLocalizations.of(context)!.importPlaylist),
                        leading: SizedBox.square(
                          dimension: 50,
                          child: Center(
                            child: Icon(
                              MdiIcons.import,
                              color: Theme.of(context).iconTheme.color,
                            ),
                          ),
                        ),
                        onTap: () async {
                          Navigator.push(
                            context,
                            MaterialPageRoute(
                              builder: (context) => ImportPlaylist(),
                            ),
                          );
                        },
                      ),
                      ListTile(
                        title: Text(AppLocalizations.of(context)!.mergePlaylists),
                        leading: SizedBox.square(
                          dimension: 50,
                          child: Center(
                            child: Icon(
                              Icons.merge_type_rounded,
                              color: Theme.of(context).iconTheme.color,
                            ),
                          ),
                        ),
                        onTap: () async {
                          final List<int> checked = [];
                          showDialog(
                            context: context,
                            builder: (BuildContext context) {
                              return StatefulBuilder(
                                builder: (
                                  BuildContext context,
                                  StateSetter setStt,
                                ) {
                                  return AlertDialog(
                                    shape: RoundedRectangleBorder(
                                      borderRadius: BorderRadius.circular(
                                        10.0,
                                      ),
                                    ),
                                    content: SizedBox(
                                      width: 500,
                                      child: ListView.builder(
                                        shrinkWrap: true,
                                        physics: const BouncingScrollPhysics(),
                                        padding: const EdgeInsets.fromLTRB(
                                          0,
                                          30,
                                          0,
                                          10,
                                        ),
                                        itemCount: playlistNames.length,
                                        itemBuilder: (context, index) {
                                          final String name =
                                              playlistNames[index].toString();
                                          final String showName =
                                              playlistDetails.containsKey(name)
                                                  ? playlistDetails[name]['name']
                                                          ?.toString() ??
                                                      name
                                                  : name;
                                          return CheckboxListTile(
                                            activeColor: Theme.of(context)
                                                .colorScheme
                                                .secondary,
                                            checkColor: Theme.of(context)
                                                        .colorScheme
                                                        .secondary ==
                                                    Colors.white
                                                ? Colors.black
                                                : null,
                                            value: checked.contains(index),
                                            onChanged: (value) {
                                              if (value ?? false) {
                                                checked.add(index);
                                              } else {
                                                checked.remove(index);
                                              }
                                              setStt(() {});
                                            },
                                            title: Text(
                                              showName,
                                              overflow: TextOverflow.ellipsis,
                                            ),
                                            subtitle:
                                                playlistDetails[name] == null ||
                                                        playlistDetails[name]
                                                                ['count'] ==
                                                            null ||
                                                        playlistDetails[name]
                                                                ['count'] ==
                                                            0
                                                    ? null
                                                    : Text(
                                                        '${playlistDetails[name]['count']} ${AppLocalizations.of(context)!.songs}',
                                                      ),
                                            secondary: (playlistDetails[name] ==
                                                        null ||
                                                    playlistDetails[name]
                                                            ['imagesList'] ==
                                                        null ||
                                                    (playlistDetails[name]
                                                                ['imagesList']
                                                            as List)
                                                        .isEmpty)
                                                ? Card(
                                                    elevation: 5,
                                                    color: Colors.transparent,
                                                    shape: RoundedRectangleBorder(
                                                      borderRadius:
                                                          BorderRadius.circular(
                                                        7.0,
                                                      ),
                                                    ),
                                                    clipBehavior: Clip.antiAlias,
                                                    child: SizedBox(
                                                      height: 50,
                                                      width: 50,
                                                      child: name ==
                                                              'Favorite Songs'
                                                          ? const Image(
                                                              image: AssetImage(
                                                                'assets/cover.jpg',
                                                              ),
                                                            )
                                                          : const Image(
                                                              image: AssetImage(
                                                                'assets/album.png',
                                                              ),
                                                            ),
                                                    ),
                                                  )
                                                : Collage(
                                                    imageList:
                                                        playlistDetails[name]
                                                                ['imagesList']
                                                            as List,
                                                    showGrid: true,
                                                    placeholderImage:
                                                        'assets/cover.jpg',
                                                  ),
                                          );
                                        },
                                      ),
                                    ),
                                    actions: [
                                      TextButton(
                                        style: TextButton.styleFrom(
                                          foregroundColor:
                                              Theme.of(context).brightness ==
                                                      Brightness.dark
                                                  ? Colors.white
                                                  : Colors.grey[700],
                                        ),
                                        onPressed: () {
                                          Navigator.pop(context);
                                        },
                                        child: Text(
                                          AppLocalizations.of(
                                            context,
                                          )!
                                              .cancel,
                                        ),
                                      ),
                                      TextButton(
                                        style: TextButton.styleFrom(
                                          foregroundColor: Theme.of(context)
                                                      .colorScheme
                                                      .secondary ==
                                                  Colors.white
                                              ? Colors.black
                                              : null,
                                          backgroundColor: Theme.of(context)
                                              .colorScheme
                                              .secondary,
                                        ),
                                        onPressed: () async {
                                          try {
                                            final List<String> playlistsToMerge =
                                                checked
                                                    .map(
                                                      (int e) => playlistNames[e]
                                                          .toString(),
                                                    )
                                                    .toList();
                                            if (playlistsToMerge
                                                .contains('Favorite Songs')) {
                                              playlistsToMerge
                                                  .remove('Favorite Songs');
                                              playlistsToMerge.insert(
                                                0,
                                                'Favorite Songs',
                                              );
                                            }
                                            if (playlistsToMerge.length > 1) {
                                              final finalMap = {};
                                              for (final String playlistName
                                                  in playlistsToMerge
                                                      .sublist(1)) {
                                                try {
                                                  final Box playlistBox =
                                                      await Hive.openBox(
                                                    playlistName,
                                                  );
                                                  final Map songsMap =
                                                      playlistBox.toMap();
                                                  finalMap.addAll(songsMap);
                                                  await playlistDetails
                                                      .remove(playlistName);
                                                  playlistNames
                                                      .remove(playlistName);
                                                  await playlistBox
                                                      .deleteFromDisk();
                                                } catch (e) {
                                                  Logger.root.severe(
                                                    'Error merging $playlistName: $e',
                                                  );
                                                  ShowSnackBar().showSnackBar(
                                                    context,
                                                    'Error merging $playlistName: $e',
                                                  );
                                                }
                                              }
                                              final Box finalPlaylistBox =
                                                  await Hive.openBox(
                                                playlistsToMerge.first,
                                              );
                                              finalPlaylistBox.putAll(finalMap);
  
                                              await settingsBox.put(
                                                'playlistDetails',
                                                playlistDetails,
                                              );
  
                                              await settingsBox.put(
                                                'playlistNames',
                                                playlistNames,
                                              );
                                            }
                                          } catch (e) {
                                            Logger.root.severe(
                                              'Error merging playlists: $e',
                                            );
                                            ShowSnackBar().showSnackBar(
                                              context,
                                              'Error: $e',
                                            );
                                          }
                                          Navigator.pop(context);
                                        },
                                        child: Text(
                                          AppLocalizations.of(
                                            context,
                                          )!
                                              .ok,
                                        ),
                                      ),
                                      const SizedBox(
                                        width: 5,
                                      ),
                                    ],
                                  );
                                },
                              );
                            },
                          );
                        },
                      ),
                      ValueListenableBuilder(
                        valueListenable: settingsBox.listenable(),
                        builder: (
                          BuildContext context,
                          Box box,
                          Widget? child,
                        ) {
                          final List playlistNamesValue = box.get(
                                'playlistNames',
                                defaultValue: ['Favorite Songs'],
                              )?.toList() as List? ??
                              ['Favorite Songs'];
                          return ListView.builder(
                            physics: const NeverScrollableScrollPhysics(),
                            shrinkWrap: true,
                            itemCount: playlistNamesValue.length,
                            itemBuilder: (context, index) {
                              final String name =
                                  playlistNamesValue[index].toString();
                              final String showName = playlistDetails
                                      .containsKey(name)
                                  ? playlistDetails[name]['name']?.toString() ??
                                      name
                                  : name;
                              return ListTile(
                                leading: (playlistDetails[name] == null ||
                                        playlistDetails[name]['imagesList'] ==
                                            null ||
                                        (playlistDetails[name]['imagesList']
                                                as List)
                                            .isEmpty)
                                    ? Card(
                                        elevation: 5,
                                        color: Colors.transparent,
                                        shape: RoundedRectangleBorder(
                                          borderRadius:
                                              BorderRadius.circular(7.0),
                                        ),
                                        clipBehavior: Clip.antiAlias,
                                        child: SizedBox(
                                          height: 50,
                                          width: 50,
                                          child: name == 'Favorite Songs'
                                              ? const Image(
                                                  image: AssetImage(
                                                    'assets/cover.jpg',
                                                  ),
                                                )
                                              : const Image(
                                                  image: AssetImage(
                                                    'assets/album.png',
                                                  ),
                                                ),
                                        ),
                                      )
                                    : Collage(
                                        imageList: playlistDetails[name]
                                            ['imagesList'] as List,
                                        showGrid: true,
                                        placeholderImage: 'assets/cover.jpg',
                                      ),
                                title: Text(
                                  showName,
                                  overflow: TextOverflow.ellipsis,
                                ),
                                subtitle: playlistDetails[name] == null ||
                                        playlistDetails[name]['count'] == null ||
                                        playlistDetails[name]['count'] == 0
                                    ? null
                                    : Text(
                                        '${playlistDetails[name]['count']} ${AppLocalizations.of(context)!.songs}',
                                      ),
                                trailing: PopupMenuButton(
                                  icon: const Icon(Icons.more_vert_rounded),
                                  shape: const RoundedRectangleBorder(
                                    borderRadius: BorderRadius.all(
                                      Radius.circular(15.0),
                                    ),
                                  ),
                                  onSelected: (int? value) async {
                                    if (value == 1) {
                                      exportPlaylist(
                                        context,
                                        name,
                                        playlistDetails.containsKey(name)
                                            ? playlistDetails[name]['name']
                                                    ?.toString() ??
                                                name
                                            : name,
                                      );
                                    }
                                    if (value == 2) {
                                      sharePlaylist(
                                        context,
                                        name,
                                        playlistDetails.containsKey(name)
                                            ? playlistDetails[name]['name']
                                                    ?.toString() ??
                                                name
                                            : name,
                                      );
                                    }
                                    if (value == 0) {
                                      ShowSnackBar().showSnackBar(
                                        context,
                                        '${AppLocalizations.of(context)!.deleted} $showName',
                                      );
                                      playlistDetails.remove(name);
                                      await settingsBox.put(
                                        'playlistDetails',
                                        playlistDetails,
                                      );
                                      await playlistNames.removeAt(index);
                                      await settingsBox.put(
                                        'playlistNames',
                                        playlistNames,
                                      );
                                      await Hive.openBox(name);
                                      await Hive.box(name).deleteFromDisk();
                                    }
                                    if (value == 3) {
                                      showDialog(
                                        context: context,
                                        builder: (BuildContext context) {
                                          final controller =
                                              TextEditingController(
                                            text: showName,
                                          );
                                          return AlertDialog(
                                            shape: RoundedRectangleBorder(
                                              borderRadius:
                                                  BorderRadius.circular(15.0),
                                            ),
                                            content: Column(
                                              mainAxisSize: MainAxisSize.min,
                                              children: [
                                                Row(
                                                  children: [
                                                    Text(
                                                      AppLocalizations.of(
                                                        context,
                                                      )!
                                                          .rename,
                                                      style: TextStyle(
                                                        color: Theme.of(context)
                                                            .colorScheme
                                                            .secondary,
                                                      ),
                                                    ),
                                                  ],
                                                ),
                                                TextField(
                                                  autofocus: true,
                                                  textAlignVertical:
                                                      TextAlignVertical.bottom,
                                                  controller: controller,
                                                  onSubmitted: (value) async {
                                                    Navigator.pop(context);
                                                    playlistDetails[name] == null
                                                        ? playlistDetails.addAll({
                                                            name: {
                                                              'name': value.trim()
                                                            }
                                                          })
                                                        : playlistDetails[name]
                                                            .addAll({
                                                            'name': value.trim()
                                                          });
  
                                                    await settingsBox.put(
                                                      'playlistDetails',
                                                      playlistDetails,
                                                    );
                                                  },
                                                ),
                                              ],
                                            ),
                                            actions: [
                                              TextButton(
                                                style: TextButton.styleFrom(
                                                  foregroundColor:
                                                      Theme.of(context)
                                                          .iconTheme
                                                          .color,
                                                ),
                                                onPressed: () {
                                                  Navigator.pop(context);
                                                },
                                                child: Text(
                                                  AppLocalizations.of(
                                                    context,
                                                  )!
                                                      .cancel,
                                                ),
                                              ),
                                              TextButton(
                                                style: TextButton.styleFrom(
                                                  foregroundColor: Colors.white,
                                                  backgroundColor:
                                                      Theme.of(context)
                                                          .colorScheme
                                                          .secondary,
                                                ),
                                                onPressed: () async {
                                                  Navigator.pop(context);
                                                  playlistDetails[name] == null
                                                      ? playlistDetails.addAll({
                                                          name: {
                                                            'name': controller
                                                                .text
                                                                .trim()
                                                          }
                                                        })
                                                      : playlistDetails[name]
                                                          .addAll({
                                                          'name': controller.text
                                                              .trim()
                                                        });
  
                                                  await settingsBox.put(
                                                    'playlistDetails',
                                                    playlistDetails,
                                                  );
                                                },
                                                child: Text(
                                                  AppLocalizations.of(
                                                    context,
                                                  )!
                                                      .ok,
                                                  style: TextStyle(
                                                    color: Theme.of(context)
                                                                .colorScheme
                                                                .secondary ==
                                                            Colors.white
                                                        ? Colors.black
                                                        : null,
                                                  ),
                                                ),
                                              ),
                                              const SizedBox(
                                                width: 5,
                                              ),
                                            ],
                                          );
                                        },
                                      );
                                    }
                                  },
                                  itemBuilder: (context) => [
                                    if (name != 'Favorite Songs')
                                      PopupMenuItem(
                                        value: 3,
                                        child: Row(
                                          children: [
                                            const Icon(Icons.edit_rounded),
                                            const SizedBox(width: 10.0),
                                            Text(
                                              AppLocalizations.of(context)!
                                                  .rename,
                                            ),
                                          ],
                                        ),
                                      ),
                                    if (name != 'Favorite Songs')
                                      PopupMenuItem(
                                        value: 0,
                                        child: Row(
                                          children: [
                                            const Icon(Icons.delete_rounded),
                                            const SizedBox(width: 10.0),
                                            Text(
                                              AppLocalizations.of(context)!
                                                  .delete,
                                            ),
                                          ],
                                        ),
                                      ),
                                    PopupMenuItem(
                                      value: 1,
                                      child: Row(
                                        children: [
                                          const Icon(MdiIcons.export),
                                          const SizedBox(width: 10.0),
                                          Text(
                                            AppLocalizations.of(context)!.export,
                                          ),
                                        ],
                                      ),
                                    ),
                                    PopupMenuItem(
                                      value: 2,
                                      child: Row(
                                        children: [
                                          const Icon(MdiIcons.share),
                                          const SizedBox(width: 10.0),
                                          Text(
                                            AppLocalizations.of(context)!.share,
                                          ),
                                        ],
                                      ),
                                    ),
                                  ],
                                ),
                                onTap: () async {
                                  await Hive.openBox(name);
                                  Navigator.push(
                                    context,
                                    MaterialPageRoute(
                                      builder: (context) => LikedSongs(
                                        playlistName: name,
                                        showName:
                                            playlistDetails.containsKey(name)
                                                ? playlistDetails[name]['name']
                                                        ?.toString() ??
                                                    name
                                                : name,
                                      ),
                                    ),
                                  );
                                },
                              );
                            },
                          );
                        },
                      )
                    ],
                  ),
                ),
              ),
            ),
            MiniPlayer(),
          ],
        ),
      );
    }
  }
  