
import 'dart:convert';
import 'dart:io';

import 'package:logger/logger.dart';
import 'package:o2oa_all_platform/common/extension/index.dart';
import 'package:o2oa_all_platform/environment_config.dart';

import 'o2_file_path_util.dart';

class OLogger {
  static void writeFromGetx(String text, {bool isError = false}) {
     Future.microtask(()=> isError ? OLogger.e('from GetX: $text') : OLogger.i('from GetX: $text'));
  }

  static final OLoggerPrinter _printer = OLoggerPrinter();

  static void v(dynamic message) {
    _printer.v(message);
  }

  static void d(dynamic message) {
    _printer.d(message);
  }

  static void i(dynamic message) {
    _printer.i(message);
  }

  static void w(dynamic message) {
    _printer.w(message);
  }

  static void e(dynamic message, [dynamic error, StackTrace? stackTrace]) {
    _printer.e(message, error, stackTrace);
  }

  static void wtf(dynamic message) {
    _printer.wtf(message);
  }
 
}

class OLoggerPrinter {

  OLoggerPrinter() {
    initLogFileOut();
  }

  Logger _logger = Logger(
    filter: ProductionFilter(),
    printer: PrefixPrinter(PrettyPrinter(methodCount: 3, printTime: true)),
    level: EnvironmentConfig.isRelease() ? Level.info : Level.verbose
  );

  Future<void> initLogFileOut() async {
    String todayFile = '${DateTime.now().ymd()}.log';
    String? filePath = await O2FilePathUtil.getLogFilePath(todayFile);
    if (filePath != null) {
      var file = File(filePath);
      if (!file.existsSync()) {
        file.createSync();
      }
      _logger = Logger(
            filter: ProductionFilter(),
            output: MultiOutput([ConsoleOutput(), FileOutput(file: file)]),
            printer: PrefixPrinter(PrettyPrinter(methodCount: 3, printTime: true)),
            level: EnvironmentConfig.isRelease() ? Level.info : Level.verbose
          );
    }
  }

  void v(dynamic message) {
    _logger.v(message);
  }

 void d(dynamic message) {
    _logger.d(message);
  }

 void i(dynamic message) {
    _logger.i(message);
  }

 void w(dynamic message) {
    _logger.w(message);
  }

 void e(dynamic message, [dynamic error, StackTrace? stackTrace]) {
    _logger.e(message, error, stackTrace);
  }

 void wtf(dynamic message) {
    _logger.wtf(message);
  } 
}

/// Writes the log output to a file.
class FileOutput extends LogOutput {
  final File file;
  final bool overrideExisting;
  final Encoding encoding;
  IOSink? _sink;

  FileOutput({
    required this.file,
    this.overrideExisting = false,
    this.encoding = utf8,
  });

  @override
  void init() {
    _sink = file.openWrite(
      mode: overrideExisting ? FileMode.writeOnly : FileMode.writeOnlyAppend,
      encoding: encoding,
    );
  }

  @override
  void output(OutputEvent event) {
    _sink?.writeAll(event.lines, '\n');
    _sink?.writeln();
  }

  @override
  void destroy() async {
    await _sink?.flush();
    await _sink?.close();
  }
}