// 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 'common.dart';
import 'layout_types.dart';

// Maps all mandatory goals from the character to eventScanCode.
//
// Mandatory goals are all the alnum keys. These keys must be assigned at the
// end of layout planning.
final Map<String, String> _kMandatoryGoalsByChar = Map<String, String>.fromEntries(
  kLayoutGoals
    .entries
    .where((MapEntry<String, String> entry) => isLetter(entry.value.codeUnitAt(0)))
    .map((MapEntry<String, String?> entry) => MapEntry<String, String>(entry.value!, entry.key))
);

/// Plan a layout into a map from eventCode to logical key.
///
/// If a eventCode does not exist in this map, then this event's logical key
/// should be derived on the fly.
///
/// This function defines the benchmark planning algorithm if there were a way
/// to know the current keyboard layout.
Map<String, int> planLayout(Map<String, LayoutEntry> entries) {
  // The logical key is derived in the following rules:
  //
  //  1. If any clue (the four possible printables) of the key is a mandatory
  //     goal (alnum), then the goal is the logical key.
  //  2. If a mandatory goal is not assigned in the way of #1, then it is
  //     assigned to the physical key as mapped in the US layout.
  //  3. Derived on the fly from key, code, and keyCode.
  //
  // The map returned from this function contains the first two rules.

  // Unresolved mandatory goals, mapped from printables to KeyboardEvent.code.
  // This map will be modified during this function and thus is a clone.
  final Map<String, String> mandatoryGoalsByChar = <String, String>{..._kMandatoryGoalsByChar};
  // The result mapping from KeyboardEvent.code to logical key.
  final Map<String, int> result = <String, int>{};

  entries.forEach((String eventCode, LayoutEntry entry) {
    for (final String printable in entry.printables) {
      if (mandatoryGoalsByChar.containsKey(printable)) {
        result[eventCode] = printable.codeUnitAt(0);
        mandatoryGoalsByChar.remove(printable);
        break;
      }
    }
  });

  // Ensure all mandatory goals are assigned.
  mandatoryGoalsByChar.forEach((String character, String code) {
    assert(!result.containsKey(code), 'Code $code conflicts.');
    result[code] = character.codeUnitAt(0);
  });
  return result;
}

bool _isLetterOrMappedToKeyCode(int charCode) {
  return isLetterChar(charCode) || charCode == kUseKeyCode;
}

/// Plan all layouts, and summarize them into a huge table of EventCode ->
/// EventKey -> logicalKey.
///
/// The resulting logicalKey can also be kUseKeyCode.
///
/// If a eventCode does not exist in this map, then this event's logical key
/// should be derived on the fly.
///
/// Entries that can be derived using heuristics are omitted.
Map<String, Map<String, int>> combineLayouts(Iterable<Layout> layouts) {
  final Map<String, Map<String, int>> result = <String, Map<String, int>>{};
  for (final Layout layout in layouts) {
    planLayout(layout.entries).forEach((String eventCode, int logicalKey) {
      final Map<String, int> codeMap = result.putIfAbsent(eventCode, () => <String, int>{});
      final LayoutEntry entry = layout.entries[eventCode]!;
      for (final String eventKey in entry.printables) {
        if (eventKey.isEmpty) {
          continue;
        }
        // Found conflict. Assert that all such cases can be solved with
        // keyCode.
        if (codeMap.containsKey(eventKey) && codeMap[eventKey] != logicalKey) {
          assert(isLetterChar(logicalKey));
          assert(_isLetterOrMappedToKeyCode(codeMap[eventKey]!), '$eventCode, $eventKey, ${codeMap[eventKey]!}');
          codeMap[eventKey] = kUseKeyCode;
        } else {
          codeMap[eventKey] = logicalKey;
        }
      }
    });
  }
  // Remove mapping results that can be derived using heuristics.
  result.removeWhere((String eventCode, Map<String, int> codeMap) {
    codeMap.removeWhere((String eventKey, int logicalKey) =>
      heuristicMapper(eventCode, eventKey) == logicalKey,
    );
    return codeMap.isEmpty;
  });
  return result;
}
