import 'package:flutter_gpiod/flutter_gpiod.dart';

class MorseService {
  final _chips = FlutterGpiod.instance.chips;

  printMessage(String message) async {
    final chip = _getRaspberryGPIO();
    final ledPin = chip.lines[18];
    ledPin.requestOutput(consumer: "morse code led", initialValue: false);
    final List<String> chars = message.toUpperCase().split('');
    const int pulseDuration = 100;

    for (var char in chars) {
      final List<String> morseCode = _morseAlphabet[char]?.split('') ?? ['*'];
      for (var code in morseCode) {
        print('CODE: $code from $morseCode');
        if (code == '*') {
          await Future.delayed(const Duration(milliseconds: pulseDuration * 7));
          break;
        }
        ledPin.setValue(true);
        print('ON');
        if (code == '.') {
          await Future.delayed(const Duration(milliseconds: pulseDuration));
        } else if (code == '-') {
          await Future.delayed(const Duration(milliseconds: pulseDuration * 3));
        }
        print('OFF');
        ledPin.setValue(false);
        // pause between letters
        await Future.delayed(const Duration(milliseconds: pulseDuration));
      }
      print("SPACE BETWEEN LETTERS");
      // space between letters is 3*pulseDuration
      await Future.delayed(const Duration(milliseconds: pulseDuration * 3));
    }

    ledPin.release();
    return true;
  }

  GpioChip _getRaspberryGPIO() {
    /// Retrieve the line with index 23 of the first chip.
    /// This is BCM pin 23 for the Raspberry Pi.
    ///
    /// I recommend finding the chip you want
    /// based on the chip label, as is done here.
    ///
    /// In this example, we search for the main Raspberry Pi GPIO chip and then
    /// retrieve the line with index 23 of it. So [line] is GPIO pin BCM 23.
    ///
    /// The main GPIO chip is called `pinctrl-bcm2711` on Pi 4 and `pinctrl-bcm2835`
    /// on older Raspberry Pis and it was also called that way on Pi 4 with older
    /// kernel versions.
    final chip = _chips.singleWhere(
      (chip) => chip.label == 'pinctrl-bcm2711',
      orElse: () =>
          _chips.singleWhere((chip) => chip.label == 'pinctrl-bcm2835'),
    );
    return chip;
  }

  // International Morse Code
  final Map<String, String> _morseAlphabet = {
    'A': '.-',
    'B': '-...',
    'C': '-.-.',
    'D': '-..',
    'E': '.',
    'F': '..-.',
    'G': '--.',
    'H': '....',
    'I': '..',
    'J': '.---',
    'K': '-.-',
    'L': '.-..',
    'M': '--',
    'N': '-.',
    'O': '---',
    'P': '.--.',
    'Q': '--.-',
    'R': '.-.',
    'S': '...',
    'T': '-',
    'U': '..-',
    'V': '...-',
    'W': '.--',
    'X': '-..-',
    'Y': '-.--',
    'Z': '--..',
    '0': '-----',
    '1': '.----',
    '2': '..---',
    '3': '...--',
    '4': '....-',
    '5': '.....',
    '6': '-....',
    '7': '--...',
    '8': '---..',
    '9': '----.',
  };
}
