import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:dartboard_resume/render.dart';
import 'package:dartboard_resume/utils.dart';
import 'package:hotreloader/hotreloader.dart';
import 'package:toml/toml.dart';

StreamSubscription<FileSystemEvent>? fileStreamSub;
StreamSubscription<String>? stdinStreamSub;

Future<void> dartboardRun(HotReloader? reloader, List<String> arguments) async {
  final result = getTomlFromArgs(arguments);
  if (!result.success) {
    exitRunner(reloader);
  }
  final resumeTomlFile = result.file!;

  if (reloader != null) {
    stdout.writeln('Hot reload enabled!');
  }

  ProcessSignal.sigint.watch().listen((_) {
    stdout.writeln('SIGINT received. Exiting gracefully...');
    exitRunner(reloader);
  });

  stdinStreamSub = getUserInputStream().listen(
    (event) {
      if (event == "r") {
        stdout.writeln("Triggering pdf render...");
        createDocument(resumeTomlFile.path);
      }
      if (event == "p") {
        stdout.writeln("Current toml map:");
        stdout.writeln(TomlDocument.loadSync(resumeTomlFile.path).toMap());
      }
      if (event == "q") {
        stdout.writeln('Exiting...');
        fileStreamSub?.cancel();
        stdinStreamSub?.cancel();
        // Perform cleanup or other necessary actions here
        reloader?.stop();
        exit(0); // Exit with code 0 to indicate a successful termination
      }
    },
  );

  if (FileSystemEntity.isWatchSupported) {
    final fileStream = resumeTomlFile.watch(events: FileSystemEvent.modify);
    fileStreamSub = fileStream.listen((e) {
      createDocument(resumeTomlFile.path);
    });
    stdout.writeln('Watching for file changes.');
  } else {
    stdout.writeln('File watch is not supported. Exiting upon completion.');
    createDocument(resumeTomlFile.path);
  }
}

Stream<String> getUserInputStream() {
  stdin.lineMode = false;
  stdin.echoMode = false;
  stdin.echoNewlineMode = false;
  return stdin.transform(const Utf8Decoder()).transform(const LineSplitter());
}

void refreshViewer() {
  final result = Process.runSync('pgrep', ['llpp']);
  if (result.exitCode != 0) {
    stdout.writeln(
      'Unable to refresh the viewer\nDartboard Resume can refresh your pdf viewer! Here are the supported programs:\n\t- llpp',
    );
    return;
  }
  // Send the HUP signal to `llpp`
  Process.runSync('pkill', ['-HUP', 'llpp']);
}

void createDocument(String tomlFilePath) {
  renderPdf(tomlFilePath, force: true);
  refreshViewer();
}

void exitRunner(HotReloader? reloader) {
  fileStreamSub?.cancel();
  stdinStreamSub?.cancel();
  // Perform cleanup or other necessary actions here
  reloader?.stop();
  exit(0); // Exit with code 0 to indicate a successful termination
}