// Copyright (c) 2018, 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:math' as math;

import 'package:charcode/charcode.dart';
import 'package:term_glyph/term_glyph.dart' as glyph;

import 'colors.dart' as colors;
import 'location.dart';
import 'span.dart';
import 'span_with_context.dart';
import 'utils.dart';

/// A class for writing a chunk of text with a particular span highlighted.
class Highlighter {
  /// The span to highlight.
  final SourceSpanWithContext _span;

  /// The color to highlight [_span] within its context, or `null` if the span
  /// should not be colored.
  final String _color;

  /// Whether [_span] covers multiple lines.
  final bool _multiline;

  /// The number of characters before the bar in the sidebar.
  final int _paddingBeforeSidebar;

  // The number of characters between the bar in the sidebar and the text
  // being highlighted.
  int get _paddingAfterSidebar =>
      // This is just a space for a single-line span, but for a multi-line span
      // needs to accommodate " | ".
      _multiline ? 3 : 1;

  /// The buffer to which to write the result.
  final _buffer = StringBuffer();

  /// The number of spaces to render for hard tabs that appear in `_span.text`.
  ///
  /// We don't want to render raw tabs, because they'll mess up our character
  /// alignment.
  static const _spacesPerTab = 4;

  /// Creates a [Highlighter] that will return a message associated with [span]
  /// when [highlight] is called.
  ///
  /// [color] may either be a [String], a [bool], or `null`. If it's a string,
  /// it indicates an [ANSI terminal color
  /// escape](https://en.wikipedia.org/wiki/ANSI_escape_code#Colors) that should
  /// be used to highlight the span's text (for example, `"\u001b[31m"` will
  /// color red). If it's `true`, it indicates that the text should be
  /// highlighted using the default color. If it's `false` or `null`, it
  /// indicates that the text shouldn't be highlighted.
  factory Highlighter(SourceSpan span, {color}) {
    if (color == true) color = colors.red;
    if (color == false) color = null;

    var newSpan = _normalizeContext(span);
    newSpan = _normalizeNewlines(newSpan);
    newSpan = _normalizeTrailingNewline(newSpan);
    newSpan = _normalizeEndOfLine(newSpan);

    return Highlighter._(newSpan, color as String);
  }

  /// Normalizes [span] to ensure that it's a [SourceSpanWithContext] whose
  /// context actually contains its text at the expected column.
  ///
  /// If it's not already a [SourceSpanWithContext], adjust the start and end
  /// locations' line and column fields so that the highlighter can assume they
  /// match up with the context.
  static SourceSpanWithContext _normalizeContext(SourceSpan span) =>
      span is SourceSpanWithContext &&
              findLineStart(span.context, span.text, span.start.column) != null
          ? span
          : SourceSpanWithContext(
              SourceLocation(span.start.offset,
                  sourceUrl: span.sourceUrl, line: 0, column: 0),
              SourceLocation(span.end.offset,
                  sourceUrl: span.sourceUrl,
                  line: countCodeUnits(span.text, $lf),
                  column: _lastLineLength(span.text)),
              span.text,
              span.text);

  /// Normalizes [span] to replace Windows-style newlines with Unix-style
  /// newlines.
  static SourceSpanWithContext _normalizeNewlines(SourceSpanWithContext span) {
    final text = span.text;
    if (!text.contains('\r\n')) return span;

    var endOffset = span.end.offset;
    for (var i = 0; i < text.length - 1; i++) {
      if (text.codeUnitAt(i) == $cr && text.codeUnitAt(i + 1) == $lf) {
        endOffset--;
      }
    }

    return SourceSpanWithContext(
        span.start,
        SourceLocation(endOffset,
            sourceUrl: span.sourceUrl,
            line: span.end.line,
            column: span.end.column),
        text.replaceAll('\r\n', '\n'),
        span.context.replaceAll('\r\n', '\n'));
  }

  /// Normalizes [span] to remove a trailing newline from `span.context`.
  ///
  /// If necessary, also adjust `span.end` so that it doesn't point past where
  /// the trailing newline used to be.
  static SourceSpanWithContext _normalizeTrailingNewline(
      SourceSpanWithContext span) {
    if (!span.context.endsWith('\n')) return span;

    // If there's a full blank line on the end of [span.context], it's probably
    // significant, so we shouldn't trim it.
    if (span.text.endsWith('\n\n')) return span;

    final context = span.context.substring(0, span.context.length - 1);
    var text = span.text;
    var start = span.start;
    var end = span.end;
    if (span.text.endsWith('\n') && _isTextAtEndOfContext(span)) {
      text = span.text.substring(0, span.text.length - 1);
      end = SourceLocation(span.end.offset - 1,
          sourceUrl: span.sourceUrl,
          line: span.end.line - 1,
          column: _lastLineLength(text));
      start = span.start.offset == span.end.offset ? end : span.start;
    }
    return SourceSpanWithContext(start, end, text, context);
  }

  /// Normalizes [span] so that the end location is at the end of a line rather
  /// than at the beginning of the next line.
  static SourceSpanWithContext _normalizeEndOfLine(SourceSpanWithContext span) {
    if (span.end.column != 0) return span;
    if (span.end.line == span.start.line) return span;

    final text = span.text.substring(0, span.text.length - 1);

    return SourceSpanWithContext(
        span.start,
        SourceLocation(span.end.offset - 1,
            sourceUrl: span.sourceUrl,
            line: span.end.line - 1,
            column: _lastLineLength(text)),
        text,
        span.context);
  }

  /// Returns the length of the last line in [text], whether or not it ends in a
  /// newline.
  static int _lastLineLength(String text) {
    if (text.isEmpty) return 0;

    // The "- 1" here avoids counting the newline itself.
    if (text.codeUnitAt(text.length - 1) == $lf) {
      return text.length == 1
          ? 0
          : text.length - text.lastIndexOf('\n', text.length - 2) - 1;
    } else {
      return text.length - text.lastIndexOf('\n') - 1;
    }
  }

  /// Returns whether [span]'s text runs all the way to the end of its context.
  static bool _isTextAtEndOfContext(SourceSpanWithContext span) =>
      findLineStart(span.context, span.text, span.start.column) +
          span.start.column +
          span.length ==
      span.context.length;

  Highlighter._(this._span, this._color)
      : _multiline = _span.start.line != _span.end.line,
        // In a purely mathematical world, floor(log10(n)) would give the number of
        // digits in n, but floating point errors render that unreliable in
        // practice.
        _paddingBeforeSidebar = (_span.end.line + 1).toString().length + 1;

  /// Returns the highlighted span text.
  ///
  /// This method should only be called once.
  String highlight() {
    _writeSidebar(end: glyph.downEnd);
    _buffer.writeln();

    // If [_span.context] contains lines prior to the one [_span.text] appears
    // on, write those first.
    final lineStart =
        findLineStart(_span.context, _span.text, _span.start.column);
    assert(lineStart != null); // enforced by [_normalizeContext]

    var context = _span.context;
    if (lineStart > 0) {
      // Take a substring to one character *before* [lineStart] because
      // [findLineStart] is guaranteed to return a position immediately after a
      // newline. Including that newline would add an extra empty line to the
      // end of [lines].
      final lines = context.substring(0, lineStart - 1).split('\n');
      var lineNumber = _span.start.line - lines.length;
      for (var line in lines) {
        _writeSidebar(line: lineNumber);
        _buffer.write(' ' * _paddingAfterSidebar);
        _writeText(line);
        _buffer.writeln();
        lineNumber++;
      }
      context = context.substring(lineStart);
    }

    final lines = context.split('\n');

    final lastLineIndex = _span.end.line - _span.start.line;
    if (lines.last.isEmpty && lines.length > lastLineIndex + 1) {
      // Trim a trailing newline so we don't add an empty line to the end of the
      // highlight.
      lines.removeLast();
    }

    _writeFirstLine(lines.first);
    if (_multiline) {
      _writeIntermediateLines(lines.skip(1).take(lastLineIndex - 1));
      _writeLastLine(lines[lastLineIndex]);
    }
    _writeTrailingLines(lines.skip(lastLineIndex + 1));

    _writeSidebar(end: glyph.upEnd);

    return _buffer.toString();
  }

  // Writes the first (and possibly only) line highlighted by the span.
  void _writeFirstLine(String line) {
    _writeSidebar(line: _span.start.line);

    var startColumn = math.min(_span.start.column, line.length);
    var endColumn = math.min(
        startColumn + _span.end.offset - _span.start.offset, line.length);
    final textBefore = line.substring(0, startColumn);

    // If the span covers the entire first line other than initial whitespace,
    // don't bother pointing out exactly where it begins.
    if (_multiline && _isOnlyWhitespace(textBefore)) {
      _buffer.write(' ');
      _colorize(() {
        _buffer..write(glyph.glyphOrAscii('┌', '/'))..write(' ');
        _writeText(line);
      });
      _buffer.writeln();
      return;
    }

    _buffer.write(' ' * _paddingAfterSidebar);
    _writeText(textBefore);
    final textInside = line.substring(startColumn, endColumn);
    _colorize(() => _writeText(textInside));
    _writeText(line.substring(endColumn));
    _buffer.writeln();

    // Adjust the start and end column to account for any tabs that were
    // converted to spaces.
    final tabsBefore = _countTabs(textBefore);
    final tabsInside = _countTabs(textInside);
    startColumn = startColumn + tabsBefore * (_spacesPerTab - 1);
    endColumn = endColumn + (tabsBefore + tabsInside) * (_spacesPerTab - 1);

    // Write the highlight for the first line. This is a series of carets for a
    // single-line span, and a pointer to the beginning of a multi-line span.
    _writeSidebar();
    if (_multiline) {
      _buffer.write(' ');
      _colorize(() {
        _buffer
          ..write(glyph.topLeftCorner)
          ..write(glyph.horizontalLine * (startColumn + 1))
          ..write('^');
      });
    } else {
      _buffer.write(' ' * (startColumn + 1));
      _colorize(
          () => _buffer.write('^' * math.max(endColumn - startColumn, 1)));
    }
    _buffer.writeln();
  }

  /// Writes the lines between the first and last lines highlighted by the span.
  void _writeIntermediateLines(Iterable<String> lines) {
    assert(_multiline);

    // +1 because the first line was already written.
    var lineNumber = _span.start.line + 1;
    for (var line in lines) {
      _writeSidebar(line: lineNumber);

      _buffer.write(' ');
      _colorize(() {
        _buffer..write(glyph.verticalLine)..write(' ');
        _writeText(line);
      });
      _buffer.writeln();

      lineNumber++;
    }
  }

  // Writes the last line highlighted by the span.
  void _writeLastLine(String line) {
    assert(_multiline);

    _writeSidebar(line: _span.end.line);

    var endColumn = math.min(_span.end.column, line.length);

    // If the span covers the entire last line, don't bother pointing out
    // exactly where it ends.
    if (_multiline && endColumn == line.length) {
      _buffer.write(' ');
      _colorize(() {
        _buffer..write(glyph.glyphOrAscii('└', '\\'))..write(' ');
        _writeText(line);
      });
      _buffer.writeln();
      return;
    }

    _buffer.write(' ');
    final textInside = line.substring(0, endColumn);
    _colorize(() {
      _buffer..write(glyph.verticalLine)..write(' ');
      _writeText(textInside);
    });
    _writeText(line.substring(endColumn));
    _buffer.writeln();

    // Adjust the end column to account for any tabs that were converted to
    // spaces.
    final tabsInside = _countTabs(textInside);
    endColumn = endColumn + tabsInside * (_spacesPerTab - 1);

    // Write the highlight for the final line, which is an arrow pointing to the
    // end of the span.
    _writeSidebar();
    _buffer.write(' ');
    _colorize(() {
      _buffer
        ..write(glyph.bottomLeftCorner)
        ..write(glyph.horizontalLine * endColumn)
        ..write('^');
    });
    _buffer.writeln();
  }

  /// Writes lines that appear in the context string but come after the span.
  void _writeTrailingLines(Iterable<String> lines) {
    // +1 because this comes after any lines covered by the span.
    var lineNumber = _span.end.line + 1;
    for (var line in lines) {
      _writeSidebar(line: lineNumber);
      _buffer.write(' ' * _paddingAfterSidebar);
      _writeText(line);
      _buffer.writeln();
      lineNumber++;
    }
  }

  /// Writes a snippet from the source text, converting hard tab characters into
  /// plain indentation.
  void _writeText(String text) {
    for (var char in text.codeUnits) {
      if (char == $tab) {
        _buffer.write(' ' * _spacesPerTab);
      } else {
        _buffer.writeCharCode(char);
      }
    }
  }

  // Writes a sidebar to [buffer] that includes [line] as the line number if
  // given and writes [end] at the end (defaults to [glyphs.verticalLine]).
  void _writeSidebar({int line, String end}) {
    _colorize(() {
      if (line != null) {
        // Add 1 to line to convert from computer-friendly 0-indexed line
        // numbers to human-friendly 1-indexed line numbers.
        _buffer.write((line + 1).toString().padRight(_paddingBeforeSidebar));
      } else {
        _buffer.write(' ' * _paddingBeforeSidebar);
      }
      _buffer.write(end ?? glyph.verticalLine);
    }, color: colors.blue);
  }

  /// Returns the number of hard tabs in [text].
  int _countTabs(String text) {
    var count = 0;
    for (var char in text.codeUnits) {
      if (char == $tab) count++;
    }
    return count;
  }

  /// Returns whether [text] contains only space or tab characters.
  bool _isOnlyWhitespace(String text) {
    for (var char in text.codeUnits) {
      if (char != $space && char != $tab) return false;
    }
    return true;
  }

  /// Colors all text written to [_buffer] during [callback], if colorization is
  /// enabled.
  ///
  /// If [color] is passed, it's used as the color; otherwise, [_color] is used.
  void _colorize(void Function() callback, {String color}) {
    if (_color != null) _buffer.write(color ?? _color);
    callback();
    if (_color != null) _buffer.write(colors.none);
  }
}
