import 'package:oto/cli/cli.dart';
import 'package:oto/oto/core/output_port.dart';

typedef CliOutputPrinter =
    Future<dynamic> Function(String value, {Color? color, Color? background});

class CliRunnerOutputPort implements RunnerOutputPort {
  final bool Function() enabled;
  final String Function() leadingPrefix;
  final CliOutputPrinter _printString;
  final CliOutputPrinter _println;

  CliRunnerOutputPort({
    required this.enabled,
    required this.leadingPrefix,
    CliOutputPrinter? printString,
    CliOutputPrinter? println,
  }) : _printString = printString ?? CLI.printString,
       _println = println ?? CLI.println;

  @override
  Future<void> line(
    String message, {
    RunnerOutputStyle style = RunnerOutputStyle.normal,
  }) async {
    if (!enabled()) return;
    await _println(message, color: _colorFor(style));
  }

  @override
  Future<void> block(
    String message, {
    RunnerOutputStyle style = RunnerOutputStyle.normal,
  }) async {
    if (!enabled()) return;
    await _printString(message, color: _colorFor(style));
  }

  @override
  Future<void> buildStep(
    String name, {
    RunnerOutputStyle style = RunnerOutputStyle.success,
  }) async {
    if (!enabled()) return;
    final message =
        '''${leadingPrefix()}*********************************************************************************************
*                            $name
*********************************************************************************************''';
    await _printString(message, color: _colorFor(style) ?? Color.green);
  }

  Color? _colorFor(RunnerOutputStyle style) {
    switch (style) {
      case RunnerOutputStyle.normal:
        return null;
      case RunnerOutputStyle.success:
        return Color.green;
      case RunnerOutputStyle.warning:
        return Color.yellowStrong;
      case RunnerOutputStyle.error:
        return Color.redStrong;
      case RunnerOutputStyle.accent:
        return Color.magenta;
      case RunnerOutputStyle.progress:
        return Color.cyan;
    }
  }
}

void setCliOutputLogHandler(void Function(String) logHandler) {
  CLI.logFunc = logHandler;
}
