// ignore_for_file: unused_element_parameter

part of 'shortcuts_manager.dart';

class _ShortcutsManagerDesktop extends ShortcutsManager {
  @override
  List<ShortcutKeyActivator> get _keysToRegister => __keysToRegister;

  late final __keysToRegister = <ShortcutKeyActivator>[
    // ------------------- playback -------------------
    ShortcutKeyActivator(
      action: HotkeyAction.play_pause,
      key: LogicalKeyboardKey.space,
      callback: Player.inst.togglePlayPause,
      title: () => "${lang.play}/${lang.pause}",
    ),
    ShortcutKeyActivator(
      action: HotkeyAction.seek_backwards,
      key: LogicalKeyboardKey.arrowLeft,
      callback: Player.inst.seekSecondsBackward,
      title: () => "<- ${lang.seekbar}",
    ),
    ShortcutKeyActivator(
      action: HotkeyAction.seek_forwards,
      key: LogicalKeyboardKey.arrowRight,
      callback: Player.inst.seekSecondsForward,
      title: () => "${lang.seekbar} ->",
    ),
    ShortcutKeyActivator(
      action: HotkeyAction.volume_up,
      key: LogicalKeyboardKey.arrowUp,
      control: true,
      includeRepeats: true,
      callback: () {
        final newVol = Player.inst.volumeUp();
        _showSnack(message: "${lang.volume} ↑: ${newVol.roundDecimals(2)}");
      },
      title: () => "${lang.volume} ↑",
    ),
    ShortcutKeyActivator(
      action: HotkeyAction.volume_down,
      key: LogicalKeyboardKey.arrowDown,
      control: true,
      includeRepeats: true,
      callback: () {
        final newVol = Player.inst.volumeDown();
        _showSnack(message: "${lang.volume} ↓: ${newVol.roundDecimals(2)}");
      },
      title: () => "${lang.volume} ↓",
    ),
    ShortcutKeyActivator(
      action: HotkeyAction.previous,
      key: LogicalKeyboardKey.arrowLeft,
      control: true,
      callback: Player.inst.previous,
      title: () => lang.previous,
    ),
    ShortcutKeyActivator(
      action: HotkeyAction.next,
      key: LogicalKeyboardKey.arrowRight,
      control: true,
      callback: Player.inst.next,
      title: () => lang.next,
    ),

    // -------------------
    ShortcutKeyActivator(
      key: LogicalKeyboardKey.keyH,
      control: true,
      callback: () {
        final currentItem = Player.inst.currentItem.value;
        final bool? newIsFav = currentItem?.execute(
          selectable: (finalItem) => PlaylistController.inst.favouriteButtonOnPressed(
            finalItem.track,
            refreshNotification: false,
          ),
          youtubeID: (finalItem) => YoutubePlaylistController.inst.favouriteButtonOnPressed(
            finalItem.id,
            refreshNotification: false,
          ),
        );
        if (newIsFav != null) {
          Player.inst.refreshNotification();
          newIsFav == true
              ? snackyy(
                  message: "${lang.favourites}: ${lang.added}",
                  icon: Broken.heart_filled,
                  leftBarIndicatorColor: Colors.green,
                )
              : snackyy(
                  message: "${lang.favourites}: ${lang.removed}",
                  icon: Broken.heart_slash,
                  leftBarIndicatorColor: Colors.red,
                );
        }
      },
      title: () => "${lang.favourites}: ${lang.add}/${lang.remove}",
    ),
    ShortcutKeyActivator(
      key: LogicalKeyboardKey.keyF,
      control: true,
      callback: () {
        if (_isInSettingsPage()) {
          NamidaSettingSearchBar.globalKey.currentState?.toggle();
        } else {
          ScrollSearchController.inst.toggleSearch(
            forceOpen: ScrollSearchController.inst.searchBarKey.currentState?.focusNode.hasPrimaryFocus != true,
            instant: true,
          );
        }
      },
      title: () => lang.search,
    ),
    ShortcutKeyActivator(
      key: LogicalKeyboardKey.keyR,
      control: true,
      callback: Indexer.inst.refreshLibraryAndCheckForDiff,
      title: () => lang.refreshLibrary,
    ),
    ShortcutKeyActivator(
      key: LogicalKeyboardKey.keyE,
      control: true,
      callback: () {
        _executeMiniPlayers(
          (localPlayer, ytPlayer, ytQueueChip) {
            if (ytPlayer != null) {
              if (ytPlayer.isExpanded) {
                ytPlayer.animateToState(false);
              } else {
                ytPlayer.animateToState(true);
              }
            } else {
              if (localPlayer.isMinimized) {
                localPlayer.snapToExpanded();
              } else {
                localPlayer.snapToMini();
              }
            }
          },
        );
      },
      title: () => lang.openMiniplayer,
    ),
    ShortcutKeyActivator(
      key: LogicalKeyboardKey.keyQ,
      control: true,
      callback: openPlayerQueue,
      title: () => lang.openQueue,
    ),
    ShortcutKeyActivator(
      key: LogicalKeyboardKey.keyL,
      control: true,
      callback: () {
        settings.save(enableLyrics: !settings.enableLyrics.value);
        final currentItem = Player.inst.currentItem.value;
        if (currentItem != null) {
          Lyrics.inst.updateLyrics(currentItem);
        }
      },
      title: () => lang.lyrics,
    ),
    ShortcutKeyActivator(
      key: LogicalKeyboardKey.keyL,
      control: true,
      shift: true,
      callback: () {
        final fullscreenState = Lyrics.inst.lrcViewKeyFullscreen.currentState;
        if (fullscreenState != null) {
          fullscreenState.exitFullScreen();
        } else {
          Lyrics.inst.lrcViewKey.currentState?.enterFullScreen();
        }
      },
      title: () => "${lang.lyrics} (${lang.fullscreen})",
    ),
    ShortcutKeyActivator(
      key: LogicalKeyboardKey.keyP,
      control: true,
      shift: true,
      callback: () {
        if (!_isInSettingsPage()) {
          const SettingsPage().navigate();
        }

        Timer(
          Duration(milliseconds: 100),
          () => NamidaSettingSearchBar.globalKey.currentState?.open(),
        );
      },
      title: () => lang.settings,
    ),
    ShortcutKeyActivator(
      key: LogicalKeyboardKey.keyS,
      control: true,
      shift: true,
      callback: () {
        final shuffleAll = settings.player.shuffleAllTracks.value;
        Player.inst.shuffleTracks(shuffleAll);
        _showSnack(
          message: "${shuffleAll ? lang.shuffleAll : lang.shuffleNext}: ${lang.done}",
        );
      },
      title: () => lang.shuffle,
    ),
    ShortcutKeyActivator(
      key: LogicalKeyboardKey.tab,
      control: true,
      callback: () {
        final e = settings.player.repeatMode.value.nextElement(PlayerRepeatMode.values);
        settings.player.save(repeatMode: e);
        _showSnack(
          message: "${lang.repeatMode}: ${e.buildText()}",
        );
      },
      title: () => lang.repeatMode,
    ),
    // -----------------
    for (int i = 1; i <= 9; i++)
      ShortcutKeyActivator(
        key: LogicalKeyboardKey(0x00000000030 + i),
        control: true,
        alt: true,
        callback: () async {
          final currentItem = Player.inst.currentItem.value;
          if (currentItem is Selectable) {
            final newRating = i * 10;
            snackyy(title: lang.rating, message: '$newRating%');

            try {
              final track = currentItem.track;
              await NamidaTaggerController.inst.updateTracksMetadata(
                tracks: [track],
                editedTags: {
                  TagField.rating: newRating.toString(),
                },
                onStatsEdit: null,
                onEdit: (didUpdate, error, _) {
                  if (!didUpdate) {
                    var msg = lang.metadataEditFailed;
                    if (error != null) msg += '\n$error';
                    snackyy(title: lang.warning, message: msg, isError: true);
                  }
                },
                keepFileDates: true,
                trimWhiteSpaces: true,
                displayFFmpegFallbackWarning: false,
              );
            } catch (e) {
              snackyy(title: lang.warning, message: e.toString(), isError: true);
            }
          }
        },
        title: () => lang.setRating,
      ),
    // -----------------
    for (int i = 1; i <= 9; i++)
      ShortcutKeyActivator(
        key: LogicalKeyboardKey(0x00000000030 + i),
        control: true,
        callback: () {
          try {
            final tab = settings.libraryTabs.value[i - 1];
            ScrollSearchController.inst.animatePageController(tab);
          } catch (_) {
            // -- index larger than tabs length
          }
        },
        title: () => lang.libraryTabs,
      ),

    // ================
    ShortcutKeyActivator(
      key: LogicalKeyboardKey.f11,
      callback: () async {
        final isFullscreen = await windowManager.isFullScreen();
        windowManager.setFullScreen(!isFullscreen);
      },
      title: () => lang.fullscreen,
    ),
    ShortcutKeyActivator(
      key: LogicalKeyboardKey.escape,
      callback: NamidaNavigator.inst.back,
      title: () => lang.exit,
    ),
  ];

  FocusAttachment? _attachment;

  @override
  void init() {
    _attachment = FocusManager.instance.rootScope.attach(
      null,
      onKeyEvent: (node, event) {
        for (final ShortcutActivator activator in bindings.keys) {
          if (activator.accepts(event, HardwareKeyboard.instance)) {
            bindings[activator]!.call();
            return KeyEventResult.handled;
          }
        }
        return KeyEventResult.ignored;
      },
    );
  }

  @override
  void initUserShortcutsFromSettings() async {
    for (final s in settings.shortcuts.shortcuts.value.entries) {
      final data = s.value;
      data?.createHotkey(s.key.toSimpleCallback());
    }
  }

  @override
  void setUserShortcut({required HotkeyAction action, required ShortcutKeyData? data}) {
    final oldShortcut = settings.shortcuts.shortcuts.value[action];
    oldShortcut?.disposeHotkey();

    data?.createHotkey(action.toSimpleCallback());
    settings.shortcuts.save(action: action, data: data);
  }

  @override
  void dispose() {
    _attachment?.detach();
  }

  @override
  void openPlayerQueue() {
    _executeMiniPlayers(
      (localPlayer, ytPlayer, ytQueueChip) {
        if (ytPlayer != null) {
          if (!ytPlayer.isExpanded) ytPlayer.animateToState(true);
          _executeYtQueueSheet(ytQueueChip, (chip) => chip.toggleSheet());
        } else {
          if (localPlayer.isInQueue) {
            localPlayer.snapToExpanded();
          } else {
            localPlayer.snapToQueue();
          }
        }
      },
    );
  }

  void _executeMiniPlayers(
    void Function(
      MiniPlayerController localPlayer,
      NamidaYTMiniplayerState? ytPlayer,
      YTMiniplayerQueueChipState? ytQueueChip,
    )
    callback,
  ) {
    callback(
      MiniPlayerController.inst,
      MiniPlayerController.inst.ytMiniplayerKey.currentState,
      NamidaNavigator.inst.ytQueueSheetKey.currentState,
    );
  }

  void _executeYtQueueSheet(YTMiniplayerQueueChipState? ytQueueChip, void Function(YTMiniplayerQueueChipState ytQueueChip) callback) {
    final ytQueue = NamidaNavigator.inst.ytQueueSheetKey.currentState;
    if (ytQueue != null) {
      callback(ytQueue);
      return;
    }

    Timer(
      const Duration(milliseconds: 100),
      () {
        final ytQueue = NamidaNavigator.inst.ytQueueSheetKey.currentState;
        if (ytQueue != null) callback(ytQueue);
      },
    );
  }

  void _showSnack({required String message}) {
    snackyy(
      icon: Broken.flash_1,
      title: lang.shortcuts,
      message: message,
      borderColor: Colors.green.withOpacityExt(0.6),
      top: false,
    );
  }

  bool _isInSettingsPage() {
    final currentRouteType = NamidaNavigator.inst.currentRoute?.route;
    final isInSettings = currentRouteType == RouteType.SETTINGS_page || currentRouteType == RouteType.SETTINGS_subpage;
    return isInSettings;
  }
}
