// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

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

import 'package:analyzer/file_system/file_system.dart';
import 'package:dartdoc/src/dartdoc_options.dart';
import 'package:dartdoc/src/package_meta.dart';
import 'package:dartdoc/src/progress_bar.dart';
import 'package:logging/logging.dart';

final _logger = Logger('dartdoc');

/// A custom [Level] for tracking file writes and verification.
///
/// Has a value of `501` – one more than [Level.FINE].
const Level _progressLevel = Level('PROGRESS', 501);

/// A custom [Level] for errant print statements.
///
/// Has a value of `1201` – one more than [Level.SHOUT].
const Level printLevel = Level('PRINT', 1201);

void logWarning(String message) {
  _logger.log(Level.WARNING, message);
}

void logInfo(String message) {
  _logger.log(Level.INFO, message);
}

void logDebug(String message) {
  _logger.log(Level.FINE, message);
}

void logProgress(String message) {
  _logger.log(_progressLevel, message);
}

/// Creates a new deterministic progress bar, and displays it (with zero
/// progress).
void progressBarStart(int totalTickCount) {
  _DartdocLogger.instance.progressBarStart(totalTickCount);
}

/// Increments the progress of the current progress bar.
void progressBarTick() {
  _DartdocLogger.instance.progressBarTick();
}

/// Updates the total length of the current progress bar.
void progressBarUpdateTickCount(int totalTickCount) {
  _DartdocLogger.instance.progressBarUpdateTickCount(totalTickCount);
}

/// Completes the current progress bar.
///
/// It is important to call this after progress is complete, in case rounding
/// errors leave the displayed progress bar at something less than 100%.
void progressBarComplete() {
  _DartdocLogger.instance.progressBarComplete();
}

abstract class Jsonable {
  /// The `String` to print when in human-readable mode
  String get text;

  /// The JSON content to print when in JSON-output mode.
  Object toJson();

  @override
  String toString() => text;
}

class _DartdocLogger {
  /// By default, we use a quiet logger.
  ///
  /// This field can be re-set, with [startLogging].
  static _DartdocLogger instance =
      _DartdocLogger._(isJson: false, isQuiet: true, showProgress: false);

  final StringSink _outSink;
  final StringSink _errSink;

  final bool _showProgressBar;

  ProgressBar? _progressBar;

  _DartdocLogger._({
    required bool isJson,
    required bool isQuiet,
    required bool showProgress,
    StringSink? outSink,
    StringSink? errSink,
  })  : _outSink = outSink ?? io.stdout,
        _errSink = errSink ?? io.stderr,
        _showProgressBar = showProgress && !isJson && !isQuiet {
    // By default, get all log output at `progressLevel` or greater.
    // This allows us to capture progress events and print `...`.
    // Change this to `Level.FINE` for debug logging.
    Logger.root.level = _progressLevel;
    if (isJson) {
      Logger.root.onRecord.listen(_onJsonRecord);
      return;
    }

    _initialize(isQuiet: isQuiet, showProgress: showProgress);
  }

  /// Initializes this as a non-JSON logger.
  ///
  /// This method mostly sets up callback behavior for each logged message.
  void _initialize({required bool isQuiet, required bool showProgress}) {
    final stopwatch = Stopwatch()..start();

    // Used to track if we're printing `...` to show progress.
    // Allows unified new-line tracking
    var writingProgress = false;
    var spinnerIndex = 0;
    const spinner = ['-', r'\', '|', '/'];

    Logger.root.onRecord.listen((record) {
      if (record.level == progressBarUpdate) {
        _outSink.write(record.message);
        return;
      }

      if (record.level == _progressLevel) {
        if (!isQuiet &&
            showProgress &&
            stopwatch.elapsed.inMilliseconds > 125) {
          if (writingProgress = false) {
            _outSink.write(' ');
          }
          writingProgress = true;
          _outSink.write('$_backspace${spinner[spinnerIndex]}');
          spinnerIndex = (spinnerIndex + 1) % spinner.length;
          stopwatch.reset();
        }
        return;
      }

      stopwatch.reset();
      if (writingProgress) {
        _outSink.write('$_backspace $_backspace');
      }
      var message = record.message;
      assert(message.isNotEmpty);

      if (record.level < Level.WARNING) {
        if (!isQuiet) {
          _outSink.writeln(message);
        }
      } else {
        if (writingProgress) {
          // Some console implementations, like IntelliJ, apparently need
          // the backspace to occur for stderr as well.
          _errSink.write('$_backspace $_backspace');
        }
        _errSink.writeln(message);
      }
      writingProgress = false;
    });
  }

  void progressBarStart(int totalTickCount) {
    if (!_showProgressBar) {
      return;
    }
    _progressBar = ProgressBar(_logger, totalTickCount);
  }

  void progressBarTick() {
    if (!_showProgressBar) {
      return;
    }
    _progressBar?.tick();
  }

  void progressBarUpdateTickCount(int totalTickCount) {
    if (!_showProgressBar) {
      return;
    }
    _progressBar?.totalTickCount = totalTickCount;
  }

  void progressBarComplete() {
    if (!_showProgressBar) {
      return;
    }
    _progressBar?.complete();
    _progressBar = null;
  }

  void _onJsonRecord(LogRecord record) {
    if (record.level == _progressLevel) {
      return;
    }

    var output = <String, dynamic>{'level': record.level.name};

    if (record.object is Jsonable) {
      output['data'] = record.object;
    } else {
      output['message'] = record.message;
    }

    _outSink.writeln(json.encode(output));
  }
}

void startLogging({
  required bool isJson,
  required bool isQuiet,
  required bool showProgress,
  StringSink? outSink,
  StringSink? errSink,
}) {
  _DartdocLogger.instance = _DartdocLogger._(
    isJson: isJson,
    isQuiet: isQuiet,
    showProgress: showProgress,
    outSink: outSink ?? io.stdout,
    errSink: errSink ?? io.stderr,
  );
}

mixin LoggingContext on DartdocOptionContextBase {
  bool get json => optionSet['json'].valueAt(context);

  bool get showProgress => optionSet['showProgress'].valueAt(context);

  bool get quiet => optionSet['quiet'].valueAt(context);
}

List<DartdocOption<Object>> createLoggingOptions(
    PackageMetaProvider packageMetaProvider) {
  var resourceProvider = packageMetaProvider.resourceProvider;
  return [
    DartdocOptionArgOnly<bool>(
      'json',
      false,
      resourceProvider,
      help: 'Prints out progress JSON maps. One entry per line.',
      negatable: true,
    ),
    DartdocOptionArgOnly<bool>(
      'showProgress',
      _terminalSupportsAnsi,
      resourceProvider,
      help: 'Display progress indications to console stdout.',
      negatable: true,
    ),
    DartdocOptionArgSynth<bool>(
      'quiet',
      (DartdocSyntheticOption<Object> option, Folder dir) =>
          option.parent['generateDocs'].valueAt(dir) == false,
      resourceProvider,
      abbr: 'q',
      negatable: true,
      help: 'Only show warnings and errors; silence all other output.',
    ),
  ];
}

const String _backspace = '\b';

bool get _terminalSupportsAnsi =>
    io.stdout.supportsAnsiEscapes &&
    io.stdioType(io.stdout) == io.StdioType.terminal;
