// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

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

void main() {
  runApp(MaterialApp(
    title: 'Hardware Key Demo',
    home: Scaffold(
      appBar: AppBar(
        title: const Text('Hardware Key Demo'),
      ),
      body: const Center(
        child: RawKeyboardDemo(),
      ),
    ),
  ));
}

class RawKeyboardDemo extends StatefulWidget {
  const RawKeyboardDemo({Key? key}) : super(key: key);

  @override
  State<RawKeyboardDemo> createState() => _HardwareKeyDemoState();
}

class _HardwareKeyDemoState extends State<RawKeyboardDemo> {
  final FocusNode _focusNode = FocusNode();
  RawKeyEvent? _event;

  @override
  void dispose() {
    _focusNode.dispose();
    super.dispose();
  }

  KeyEventResult _handleKeyEvent(FocusNode node, RawKeyEvent event) {
    setState(() {
      _event = event;
    });
    return KeyEventResult.ignored;
  }

  String _asHex(int value) => value != null ? '0x${value.toRadixString(16)}' : 'null';

  String _getEnumName(dynamic enumItem) {
    final String name = '$enumItem';
    final int index = name.indexOf('.');
    return index == -1 ? name : name.substring(index + 1);
  }

  @override
  Widget build(BuildContext context) {
    final TextTheme textTheme = Theme.of(context).textTheme;
    return Focus(
      focusNode: _focusNode,
      onKey: _handleKeyEvent,
      autofocus: true,
      child: AnimatedBuilder(
        animation: _focusNode,
        builder: (BuildContext context, Widget? child) {
          if (!_focusNode.hasFocus) {
            return GestureDetector(
              onTap: () {
                _focusNode.requestFocus();
              },
              child: Text('Tap to focus', style: textTheme.headline4),
            );
          }

          if (_event == null) {
            return Text('Press a key', style: textTheme.headline4);
          }

          final RawKeyEventData? data = _event?.data;
          final String? modifierList = data?.modifiersPressed.keys.map<String>(_getEnumName).join(', ').replaceAll('Modifier', '');
          final List<Widget> dataText = <Widget>[
            Text('${_event.runtimeType}'),
            if (_event?.character?.isNotEmpty ?? false) Text('character produced: "${_event?.character}"'),
            Text('modifiers set: $modifierList'),
          ];
          if (data is RawKeyEventDataAndroid) {
            const int combiningCharacterMask = 0x7fffffff;
            final String codePointChar = String.fromCharCode(combiningCharacterMask & data.codePoint);
            dataText.add(Text('codePoint: ${data.codePoint} (${_asHex(data.codePoint)}: $codePointChar)'));
            final String plainCodePointChar = String.fromCharCode(combiningCharacterMask & data.plainCodePoint);
            dataText.add(Text('plainCodePoint: ${data.plainCodePoint} (${_asHex(data.plainCodePoint)}: $plainCodePointChar)'));
            dataText.add(Text('keyCode: ${data.keyCode} (${_asHex(data.keyCode)})'));
            dataText.add(Text('scanCode: ${data.scanCode} (${_asHex(data.scanCode)})'));
            dataText.add(Text('metaState: ${data.metaState} (${_asHex(data.metaState)})'));
            dataText.add(Text('source: ${data.eventSource} (${_asHex(data.eventSource)})'));
            dataText.add(Text('vendorId: ${data.vendorId} (${_asHex(data.vendorId)})'));
            dataText.add(Text('productId: ${data.productId} (${_asHex(data.productId)})'));
            dataText.add(Text('flags: ${data.flags} (${_asHex(data.flags)})'));
            dataText.add(Text('repeatCount: ${data.repeatCount} (${_asHex(data.repeatCount)})'));
          } else if (data is RawKeyEventDataFuchsia) {
            dataText.add(Text('codePoint: ${data.codePoint} (${_asHex(data.codePoint)})'));
            dataText.add(Text('hidUsage: ${data.hidUsage} (${_asHex(data.hidUsage)})'));
            dataText.add(Text('modifiers: ${data.modifiers} (${_asHex(data.modifiers)})'));
          } else if (data is RawKeyEventDataMacOs) {
            dataText.add(Text('keyCode: ${data.keyCode} (${_asHex(data.keyCode)})'));
            dataText.add(Text('characters: ${data.characters}'));
            dataText.add(Text('charactersIgnoringModifiers: ${data.charactersIgnoringModifiers}'));
            dataText.add(Text('modifiers: ${data.modifiers} (${_asHex(data.modifiers)})'));
          } else if (data is RawKeyEventDataLinux) {
            dataText.add(Text('keyCode: ${data.keyCode} (${_asHex(data.keyCode)})'));
            dataText.add(Text('scanCode: ${data.scanCode}'));
            dataText.add(Text('unicodeScalarValues: ${data.unicodeScalarValues}'));
            dataText.add(Text('modifiers: ${data.modifiers} (${_asHex(data.modifiers)})'));
          } else if (data is RawKeyEventDataWindows) {
            dataText.add(Text('keyCode: ${data.keyCode} (${_asHex(data.keyCode)})'));
            dataText.add(Text('scanCode: ${data.scanCode}'));
            dataText.add(Text('characterCodePoint: ${data.characterCodePoint}'));
            dataText.add(Text('modifiers: ${data.modifiers} (${_asHex(data.modifiers)})'));
          } else if (data is RawKeyEventDataWeb) {
            dataText.add(Text('key: ${data.key}'));
            dataText.add(Text('code: ${data.code}'));
            dataText.add(Text('metaState: ${data.metaState} (${_asHex(data.metaState)})'));
          }
          dataText.add(Text('logical: ${_event?.logicalKey}'));
          dataText.add(Text('physical: ${_event?.physicalKey}'));
          if (_event?.character != null) {
            dataText.add(Text('character: ${_event?.character}'));
          }
          for (final ModifierKey modifier in data!.modifiersPressed.keys) {
            for (final KeyboardSide side in KeyboardSide.values) {
              if (data.isModifierPressed(modifier, side: side)) {
                dataText.add(
                  Text('${_getEnumName(side)} ${_getEnumName(modifier).replaceAll('Modifier', '')} pressed'),
                );
              }
            }
          }
          final List<String> pressed = <String>['Pressed:'];
          for (final LogicalKeyboardKey key in RawKeyboard.instance.keysPressed) {
            pressed.add(key.debugName!);
          }
          dataText.add(Text(pressed.join(' ')));
          return DefaultTextStyle(
            style: textTheme.subtitle1!,
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: dataText,
            ),
          );
        },
      ),
    );
  }
}
