// ignore_for_file: depend_on_referenced_packages

import 'dart:io';

import 'package:dart_framework/utils/system_util.dart';
import 'package:oto/cli/commands/command_base.dart';
import 'package:oto/cli/commands/command_manager.dart';
import 'package:path/path.dart' as path;

import 'cli_style.dart';
import 'printer.dart';
export 'cli_style.dart';
export 'printer.dart';

class CLIConfig {
  String serviceName;
  List<String> arguments;
  List<CommandBase> commands;
  late String executableFileName;
  CLIConfig(this.serviceName, this.arguments, this.commands) {
    var fileName = path.basename(Platform.resolvedExecutable);
    fileName = fileName.replaceAll(path.extension(fileName), '');
    if (fileName == 'dart') {
      //debug
      fileName = 'dart bin/main.dart';
    }
    executableFileName = fileName;
  }
}

class CLI {
  static Printer get printer {
    if (Platform.isWindows) {
      return Printer.windows();
    } else {
      return Printer.unix();
    }
  }

  static Function(String)? _logFunc;
  static set logFunc(Function(String) value) {
    _logFunc = value;
  }

  CLI._privateConstructor();
  static final CLI _instance = CLI._privateConstructor();
  static CLI get current => _instance;
  static void initialize(
      String serviceName, List<String> arguments, List<CommandBase> commands) {
    current.start(serviceName, arguments, commands);
  }

  static String style(String message,
      {Color? color, Color? background, Style? style}) {
    return printer.getStyle(message,
        color: color, background: background, style: style);
  }

  static final commandNameSpace = 21;
  static String get serviceName => CLI.current.config.serviceName;
  static String get executableFileName => CLI.current.config.executableFileName;

  static Future print(List<String> printList,
      {Color? color, Color? background}) async {
    if (_logFunc == null) {
      if (color != null || background != null) {
        for (var i = 0; i < printList.length; ++i) {
          printList[i] =
              CLI.style(printList[i], color: color, background: background);
        }
      }
      await printer.printCLI(printList);
    } else {
      _logFunc!(printList.join('\n'));
    }
    return simpleFuture;
  }

  static Future printBuffer(StringBuffer buffer,
      {Color? color, Color? background}) async {
    return await printString(buffer.toString(),
        color: color, background: background);
  }

  static Future printString(String str,
      {Color? color, Color? background}) async {
    str = str.replaceAll('\r', '');
    return await print(str.split('\n'), color: color, background: background);
  }

  static Future println(String str, {Color? color, Color? background}) async {
    str = str.replaceAll('\n', '').replaceAll('\r', '');
    return await printString(str, color: color, background: background);
  }

  late CLIConfig config;
  late CommandManager _commandManager;

  void start(String serviceName, List<String> arguments,
      List<CommandBase> commands) async {
    config = CLIConfig(serviceName, arguments, commands);
    _commandManager = CommandManager(config.commands);

    //find command
    String? command;
    var args = config.arguments.toList();
    if (arguments.isNotEmpty) {
      for (var value in args) {
        command = value;
        break;
      }

      args.removeAt(0);
    }
    await _commandManager.execute(command, args);
  }
}
