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

import '../l10n/generated/app_localizations.dart';
import '../src/rust/api.dart' as rust;

/// Server connection form.
class ConnectForm extends StatefulWidget {
  /// Construct a connect form.
  const ConnectForm({
    super.key,
    required this.hostCtl,
    required this.nickCtl,
    required this.passwordCtl,
    required this.onConnect,
    required this.onAddBookmark,
  });

  /// Server host controller.
  final TextEditingController hostCtl;

  /// Nickname controller.
  final TextEditingController nickCtl;

  /// Server password controller.
  final TextEditingController passwordCtl;

  /// Called when the user submits a connection.
  final VoidCallback onConnect;

  /// Called when the user saves the current form as a bookmark.
  final VoidCallback onAddBookmark;

  @override
  State<ConnectForm> createState() => _ConnectFormState();
}

class _ConnectFormState extends State<ConnectForm> {
  final FocusNode _hostFocus = FocusNode();
  final FocusNode _nickFocus = FocusNode();
  final FocusNode _passwordFocus = FocusNode();

  void _onTapOutside(PointerDownEvent _) {
    FocusManager.instance.primaryFocus?.unfocus();
  }

  @override
  void dispose() {
    _hostFocus.dispose();
    _nickFocus.dispose();
    _passwordFocus.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final l10n = AppL10n.of(context);
    return Column(
      crossAxisAlignment: CrossAxisAlignment.stretch,
      children: [
        TextField(
          controller: widget.hostCtl,
          focusNode: _hostFocus,
          onTapOutside: _onTapOutside,
          keyboardType: TextInputType.url,
          textCapitalization: TextCapitalization.none,
          textInputAction: TextInputAction.next,
          autocorrect: false,
          enableSuggestions: false,
          inputFormatters: [
            FilteringTextInputFormatter.deny(RegExp(r'\s')),
            TextInputFormatter.withFunction(
              (oldValue, newValue) => newValue.copyWith(
                text: newValue.text.toLowerCase(),
                selection: newValue.selection,
              ),
            ),
          ],
          decoration: InputDecoration(
            labelText: l10n.fieldServerHost,
            hintText: 'host[:port]',
            prefixIcon: const Icon(Icons.dns_outlined),
            border: const OutlineInputBorder(),
          ),
        ),
        const SizedBox(height: 8),
        TextField(
          controller: widget.nickCtl,
          focusNode: _nickFocus,
          onTapOutside: _onTapOutside,
          textInputAction: TextInputAction.next,
          autocorrect: false,
          enableSuggestions: false,
          decoration: InputDecoration(
            labelText: l10n.fieldNickname,
            border: const OutlineInputBorder(),
          ),
        ),
        const SizedBox(height: 8),
        TextField(
          controller: widget.passwordCtl,
          focusNode: _passwordFocus,
          onTapOutside: _onTapOutside,
          obscureText: true,
          textInputAction: TextInputAction.done,
          autocorrect: false,
          enableSuggestions: false,
          decoration: InputDecoration(
            labelText: l10n.fieldServerPassword,
            helperText: l10n.fieldServerPasswordHelp,
            border: const OutlineInputBorder(),
          ),
        ),
        const SizedBox(height: 16),
        LayoutBuilder(
          builder: (context, constraints) {
            const stackedActionsMaxWidth = 400.0;
            final connectButton = FilledButton.icon(
              icon: const Icon(Icons.login),
              label: Text(l10n.connectAction),
              onPressed: widget.onConnect,
            );
            final bookmarkButton = OutlinedButton.icon(
              icon: const Icon(Icons.bookmark_add_outlined),
              label: Text(l10n.bookmarkAddAction),
              onPressed: widget.onAddBookmark,
            );
            if (constraints.maxWidth <= stackedActionsMaxWidth) {
              return Column(
                crossAxisAlignment: CrossAxisAlignment.stretch,
                children: [
                  connectButton,
                  const SizedBox(height: 8),
                  bookmarkButton,
                ],
              );
            }
            return Row(
              children: [
                Expanded(child: connectButton),
                const SizedBox(width: 8),
                Flexible(child: bookmarkButton),
              ],
            );
          },
        ),
      ],
    );
  }
}

/// Saved bookmark list.
class BookmarkList extends StatelessWidget {
  /// Construct a bookmark list.
  const BookmarkList({
    super.key,
    required this.bookmarks,
    required this.onConnect,
    required this.onDelete,
  });

  /// Saved bookmarks.
  final List<rust.BridgeBookmark> bookmarks;

  /// Connect to a bookmark.
  final ValueChanged<rust.BridgeBookmark> onConnect;

  /// Delete a bookmark.
  final ValueChanged<rust.BridgeBookmark> onDelete;

  @override
  Widget build(BuildContext context) {
    final l10n = AppL10n.of(context);
    final theme = Theme.of(context);
    if (bookmarks.isEmpty) {
      return Padding(
        padding: const EdgeInsets.symmetric(vertical: 8),
        child: Text(l10n.bookmarksEmpty, style: theme.textTheme.bodySmall),
      );
    }
    return Column(
      crossAxisAlignment: CrossAxisAlignment.stretch,
      children: [
        Text(l10n.bookmarksHeading, style: theme.textTheme.titleSmall),
        const SizedBox(height: 4),
        for (final b in bookmarks)
          Card(
            margin: const EdgeInsets.symmetric(vertical: 4),
            child: ListTile(
              title: Text(b.displayName),
              subtitle: Text('${b.host} — ${b.nickname}'),
              trailing: Row(
                mainAxisSize: MainAxisSize.min,
                children: [
                  IconButton(
                    icon: const Icon(Icons.login),
                    tooltip: l10n.connectAction,
                    onPressed: () => onConnect(b),
                  ),
                  IconButton(
                    icon: const Icon(Icons.delete_outline),
                    tooltip: l10n.bookmarkDeleteAction,
                    onPressed: () => onDelete(b),
                  ),
                ],
              ),
            ),
          ),
      ],
    );
  }
}
