// 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:path/path.dart' as path;

import 'base_code_gen.dart';
import 'constants.dart';
import 'logical_key_data.dart';
import 'physical_key_data.dart';
import 'utils.dart';

/// Given an [input] string, wraps the text at 80 characters and prepends each
/// line with the [prefix] string. Use for generated comments.
String _wrapString(String input) {
  return wrapString(input, prefix: '  /// ');
}

final List<MaskConstant> _maskConstants = <MaskConstant>[
  kValueMask,
  kPlaneMask,
  kUnicodePlane,
  kUnprintablePlane,
  kFlutterPlane,
  kStartOfPlatformPlanes,
  kAndroidPlane,
  kFuchsiaPlane,
  kIosPlane,
  kMacosPlane,
  kGtkPlane,
  kWindowsPlane,
  kWebPlane,
  kGlfwPlane,
];

class SynonymKeyInfo {
  SynonymKeyInfo(this.keys, this.name);

  final List<LogicalKeyEntry> keys;
  final String name;

  // Use the first item in the synonyms as a template for the ID to use.
  // It won't end up being the same value because it'll be in the pseudo-key
  // plane.
  LogicalKeyEntry get primaryKey => keys[0];
  String get constantName => upperCamelToLowerCamel(name);
}

/// Generates the keyboard_key.dart based on the information in the key data
/// structure given to it.
class KeyboardKeysCodeGenerator extends BaseCodeGenerator {
  KeyboardKeysCodeGenerator(PhysicalKeyData keyData, LogicalKeyData logicalData) : super(keyData, logicalData);

  /// Gets the generated definitions of PhysicalKeyboardKeys.
  String get _physicalDefinitions {
    final OutputLines<int> lines = OutputLines<int>('Physical Key Definition');
    for (final PhysicalKeyEntry entry in keyData.entries) {
      final String firstComment = _wrapString('Represents the location of the '
        '"${entry.commentName}" key on a generalized keyboard.');
      final String otherComments = _wrapString('See the function '
        '[RawKeyEvent.physicalKey] for more information.');
      lines.add(entry.usbHidCode, '''
$firstComment  ///
$otherComments  static const PhysicalKeyboardKey ${entry.constantName} = PhysicalKeyboardKey(${toHex(entry.usbHidCode)});
''');
    }
    return lines.sortedJoin().trimRight();
  }

  String get _physicalDebugNames {
    final OutputLines<int> lines = OutputLines<int>('Physical debug names');
    for (final PhysicalKeyEntry entry in keyData.entries) {
      lines.add(entry.usbHidCode, '''
      ${toHex(entry.usbHidCode)}: '${entry.commentName}',''');
    }
    return lines.sortedJoin().trimRight();
  }

  /// Gets the generated definitions of LogicalKeyboardKeys.
  String get _logicalDefinitions {
    final OutputLines<int> lines = OutputLines<int>('Logical debug names');
    void printKey(int flutterId, String constantName, String commentName, {String? otherComments}) {
      final String firstComment = _wrapString('Represents the logical "$commentName" key on the keyboard.');
      otherComments ??= _wrapString('See the function [RawKeyEvent.logicalKey] for more information.');
      lines.add(flutterId, '''
$firstComment  ///
$otherComments  static const LogicalKeyboardKey $constantName = LogicalKeyboardKey(${toHex(flutterId, digits: 11)});
''');
    }

    for (final LogicalKeyEntry entry in logicalData.entries) {
      printKey(
        entry.value,
        entry.constantName,
        entry.commentName,
        otherComments: _otherComments(entry.name),
      );
    }
    return lines.sortedJoin().trimRight();
  }

  String? _otherComments(String name) {
    if (synonyms.containsKey(name)) {
      final Set<String> unionNames = synonyms[name]!.keys.map(
        (LogicalKeyEntry entry) => entry.constantName).toSet();
      return _wrapString('This key represents the union of the keys '
              '$unionNames when comparing keys. This key will never be generated '
              'directly, its main use is in defining key maps.');
    }
    return null;
  }

  String get _logicalSynonyms {
    final StringBuffer result = StringBuffer();
    for (final SynonymKeyInfo synonymInfo in synonyms.values) {
      for (final LogicalKeyEntry key in synonymInfo.keys) {
        final LogicalKeyEntry synonym = logicalData.entryByName(synonymInfo.name);
        result.writeln('    ${key.constantName}: ${synonym.constantName},');
      }
    }
    return result.toString();
  }

  String get _logicalKeyLabels {
    final OutputLines<int> lines = OutputLines<int>('Logical key labels');
    for (final LogicalKeyEntry entry in logicalData.entries) {
      lines.add(entry.value, '''
    ${toHex(entry.value, digits: 11)}: '${entry.commentName}',''');
    }
    return lines.sortedJoin().trimRight();
  }

  /// This generates the map of USB HID codes to physical keys.
  String get _predefinedHidCodeMap {
    final OutputLines<int> lines = OutputLines<int>('Physical key map');
    for (final PhysicalKeyEntry entry in keyData.entries) {
      lines.add(entry.usbHidCode, '    ${toHex(entry.usbHidCode)}: ${entry.constantName},');
    }
    return lines.sortedJoin().trimRight();
  }

  /// This generates the map of Flutter key codes to logical keys.
  String get _predefinedKeyCodeMap {
    final OutputLines<int> lines = OutputLines<int>('Logical key map');
    for (final LogicalKeyEntry entry in logicalData.entries) {
      lines.add(entry.value, '    ${toHex(entry.value, digits: 11)}: ${entry.constantName},');
    }
    return lines.sortedJoin().trimRight();
  }

  String get _maskConstantVariables {
    final OutputLines<int> lines = OutputLines<int>('Mask constants', checkDuplicate: false);
    for (final MaskConstant constant in _maskConstants) {
      lines.add(constant.value, '''
${_wrapString(constant.description)}  ///
  /// This is used by platform-specific code to generate Flutter key codes.
  static const int ${constant.lowerCamelName} = ${toHex(constant.value, digits: 11)};
''');
    }
    return lines.join().trimRight();
  }

  @override
  String get templatePath => path.join(dataRoot, 'keyboard_key.tmpl');

  @override
  Map<String, String> mappings() {
    return <String, String>{
      'LOGICAL_KEY_MAP': _predefinedKeyCodeMap,
      'LOGICAL_KEY_DEFINITIONS': _logicalDefinitions,
      'LOGICAL_KEY_SYNONYMS': _logicalSynonyms,
      'LOGICAL_KEY_KEY_LABELS': _logicalKeyLabels,
      'PHYSICAL_KEY_MAP': _predefinedHidCodeMap,
      'PHYSICAL_KEY_DEFINITIONS': _physicalDefinitions,
      'PHYSICAL_KEY_DEBUG_NAMES': _physicalDebugNames,
      'MASK_CONSTANTS': _maskConstantVariables,
    };
  }

  late final Map<String, SynonymKeyInfo> synonyms = Map<String, SynonymKeyInfo>.fromEntries(
    LogicalKeyData.synonyms.entries.map((MapEntry<String, List<String>> synonymDefinition) {
      final List<LogicalKeyEntry> entries = synonymDefinition.value.map(
        (String name) => logicalData.entryByName(name)).toList();
      return MapEntry<String, SynonymKeyInfo>(
        synonymDefinition.key,
        SynonymKeyInfo(
          entries,
          synonymDefinition.key,
        ),
      );
    }),
  );
}
