#!/usr/bin/env dart
// Copyright (c) 2014, 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.

// ----------------------------------------------------------------------
// This is a very specialized tool which was created in order to support
// adding hash values used as location markers in the LaTeX source of the
// language specification.  It is intended to take its input file as the
// first argument, an output file name as the second argument, and a
// hash listing file name as the third argument. From docs/language a
// typical usage would be as follows:
//
// dart ../../tools/addlatexhash.dart dartLangSpec.tex out.tex hash.txt
//
// This will produce a normalized variant out.tex of the language
// specification with hash values filled in, and a listing hash.txt of
// all the hash values along with the label of their textual context
// (section, subsection, subsubsection, paragraph) .  For more details,
// please check the language specification source itself.
//
// NB: This utility assumes UN*X style line endings, \n, in the LaTeX
// source file received as input; it will not work with other styles.

// ignore_for_file: constant_identifier_names, only_throw_errors

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

import 'package:convert/convert.dart';
import 'package:crypto/crypto.dart';

// ----------------------------------------------------------------------
// Normalization of the text: removal or normalization of parts that
// do not affect the output from latex, such as white space.

final commentRE = RegExp(r'[^\\]%.*'); // NB: . does not match \n.
final whitespaceAllRE = RegExp(r'^\s+$');
final whitespaceRE = RegExp(r'(?:(?=\s).){2,}'); // \s except end-of-line

/// Removes [match]ing part of [line], adjusting that part with the
/// given [startOffset] and [endOffset], bounded to be valid indices
/// into the string if needed, then inserts [glue] where text was
/// removed.  If there is no match then [line] is returned.
String cutMatch(String line, RegExpMatch? match,
    {int startOffset = 0, int endOffset = 0, String glue = ''}) {
  if (match == null) return line;
  var start = match.start + startOffset;
  var end = match.end + endOffset;
  var len = line.length;
  if (start < 0) start = 0;
  if (end > len) end = len;
  return line.substring(0, start) + glue + line.substring(end);
}

String cutRegexp(String line, RegExp re,
    {int startOffset = 0, int endOffset = 0, String glue = ''}) {
  return cutMatch(line, re.firstMatch(line),
      startOffset: startOffset, endOffset: endOffset, glue: glue);
}

bool isWsOnly(String line) => line.contains(whitespaceAllRE);
bool isCommentOnly(String line) => line.startsWith('%');

/// Returns the end-of-line character at the end of [line], if any,
/// otherwise returns the empty string.
String justEol(String line) => line.endsWith('\n') ? '\n' : '';

/// Removes the contents of the comment at the end of [line],
/// leaving the "%" in place.  If no comment is present,
/// return [line].
///
/// NB: it is tempting to remove everything from the '%' and out,
/// including the final newline, if any, but this does not work.
/// The problem is that TeX will do exactly this, but then it will
/// add back a character that depends on its state (S, M, or N),
/// and it is tricky to maintain a similar state that matches the
/// state of TeX faithfully.  Hence, we remove the content of
/// comments but do not remove the comments themselves, we just
/// leave the '%' at the end of the line and let TeX manage its
/// states in a way that does not differ from the file from before
/// stripComment.
String stripComment(String line) {
  if (isCommentOnly(line)) return '%\n';
  return cutRegexp(line, commentRE, startOffset: 2);
}

/// Reduces a white-space-only [line] to its eol character,
/// removes leading ws entirely, and reduces multiple
/// white-space chars to one.
String normalizeWhitespace(String line) {
  var trimLine = line.trimLeft();
  if (trimLine.isEmpty) return justEol(line);
  return trimLine.replaceAll(whitespaceRE, ' ');
}

/// Reduces sequences of >1 white-space-only lines in [lines] to 1,
/// and sequences of >1 comment-only lines to 1.  Treats comment-only
/// lines as white-space-only when they occur in white-space-only
/// line blocks.
List<String> multilineNormalize(List<String> lines) {
  var afterBlankLines = false; // Does [line] succeed >0 empty lines?
  var afterCommentLines = false; // Does [line] succeed >0 commentOnly lines?
  var newLines = <String>[];
  for (var line in lines) {
    if (afterBlankLines && afterCommentLines) {
      // Previous line was both blank and a comment: not possible.
      throw 'Bug, please report to eernst@';
    } else if (afterBlankLines && !afterCommentLines) {
      // At least one line before [line] is wsOnly.
      if (!isWsOnly(line)) {
        // Blank line block ended.
        afterCommentLines = isCommentOnly(line);
        // Special case: It seems to be safe to remove commentOnly lines
        // after wsOnly lines, so the TeX state must be predictably right;
        // next line will then be afterCommentLines and be dropped, so
        // we drop the entire comment block---which is very useful.  We can
        // also consider this comment line to be an empty line, such that
        // subsequent empty lines can be considered to be in a block of
        // empty lines.  Note that almost all variants of this breaks.
        if (afterCommentLines) {
          // _Current_ 'line' is a commentOnly here.
          afterBlankLines = true;
          afterCommentLines = false;
          // Omit addition of [line].
        } else {
          // After blanks, but current 'line' is neither blank nor comment.
          afterBlankLines = false;
          newLines.add(line);
        }
      } else {
        // Blank line block continues, omit addition of [line].
      }
    } else if (!afterBlankLines && afterCommentLines) {
      // At least one line before [line] is commentOnly.
      if (!isCommentOnly(line)) {
        // Comment block ended.
        afterBlankLines = isWsOnly(line);
        afterCommentLines = false;
        newLines.add(line);
      } else {
        // Comment block continues, do not add [line].
      }
    } else {
      assert(!afterBlankLines && !afterCommentLines);
      // No wsOnly or commentOnly lines precede [line].
      afterBlankLines = isWsOnly(line);
      afterCommentLines = isCommentOnly(line);
      if (!afterCommentLines) {
        newLines.add(line);
      } else {
        // skip commentOnly line after nonWs/nonComment text.
      }
    }
  }
  return newLines;
}

/// Selects the elements in the normalization pipeline.
String normalize(String line) => normalizeWhitespace(stripComment(line));

/// Selects the elements in the significant-spacing block
/// normalization pipeline.
String sispNormalize(String line) => stripComment(line);

// Managing fragments with significant spacing.

final dartCodeBeginRE = RegExp(r'^\s*\\begin\s*\{dartCode\}');
final dartCodeEndRE = RegExp(r'^\s*\\end\s*\{dartCode\}');

/// Recognizes beginning of dartCode block.
bool sispIsDartBegin(String line) => line.contains(dartCodeBeginRE);

/// Recognizes end of dartCode block.
bool sispIsDartEnd(String line) => line.contains(dartCodeEndRE);

// ----------------------------------------------------------------------
// Analyzing the input to point out "interesting" lines

/// Returns the event information for [lines] as determined by the
/// given [analyzer].  The method [HashAnalyzer.analyze] indicates that a
/// line is "uninteresting" by returning null (i.e., no events here).
List<HashEvent> findEvents(List<String> lines, HashAnalyzer analyzer) {
  var events = <HashEvent>[];
  for (var line in lines) {
    var event = analyzer.analyze(line);
    if (event != null) events.add(event);
  }
  return events;
}

/// Returns RegExp text for recognizing a command occupying a line
/// of its own, given the part of the RegExp that recognizes the
/// command name, [cmdNameRE]
RegExp lineCommandRE(String cmdNameRE) =>
    RegExp(r'^\s*\\' + cmdNameRE + r'\s*\{.*\}%?\s*$');

final hashLabelStartRE = RegExp(r'^\s*\\LMLabel\s*\{');
final hashLabelEndRE = RegExp(r'\}\s*$');

final hashMarkRE = lineCommandRE('LMHash');
final hashLabelRE = lineCommandRE('LMLabel');
final sectioningRE = lineCommandRE('((|sub(|sub))section|paragraph)');
final sectionRE = lineCommandRE('section');
final subsectionRE = lineCommandRE('subsection');
final subsubsectionRE = lineCommandRE('subsubsection');
final paragraphRE = lineCommandRE('paragraph');

/// Returns true iff [line] begins a block of lines that gets a hash value.
bool isHashMarker(String line) => line.contains(hashMarkRE);

/// Returns true iff [line] defines a sectioning label.
bool isHashLabel(String line) => line.contains(hashLabelRE);

/// Returns true iff [line] is a sectioning command resp. one of its
/// more specific forms; note that it is assumed that sectioning commands
/// do not contain a newline between the command name and the '{'.
bool isSectioningCommand(String line) => line.contains(sectioningRE);
bool isSectionCommand(String line) => line.contains(sectionRE);
bool isSubsectionCommand(String line) => line.contains(subsectionRE);
bool isSubsubsectionCommand(String line) => line.contains(subsubsectionRE);
bool isParagraphCommand(String line) => line.contains(paragraphRE);

/// Returns true iff [line] does not end a block of lines that gets
/// a hash value.
bool isntHashBlockTerminator(String line) => !isSectioningCommand(line);

/// Returns the label text part from [line], based on the assumption
/// that isHashLabel(line) returns true.
String extractHashLabel(String line) {
  var startMatch = hashLabelStartRE.firstMatch(line);
  var endMatch = hashLabelEndRE.firstMatch(line);
  if (startMatch != null && endMatch != null) {
    return line.substring(startMatch.end, endMatch.start);
  } else {
    throw 'Assertion failure (so this file is both valid nnbd and not)';
  }
}

// Event classes: Keep track of relevant information about the LaTeX
// source code lines, such as where \LMHash and \LMLabel commands are
// used, and how they are embedded in the sectioning structure.

/// Abstract events, enabling us to [setEndLineNumber] on all events.
abstract class HashEvent {
  /// For events that have an endLineNumber, set it; otherwise ignore.
  /// The endLineNumber specifies the end of the block of lines
  /// associated with a given event, for event types concerned with
  /// blocks of lines rather than single lines.
  void setEndLineNumber(int n) {}

  /// Returns null except for \LMHash{} events, where it returns
  /// the startLineNumber.  This serves to specify a boundary because
  /// the preceding \LMHash{} block should stop before the line of
  /// this \LMHash{} command.  Note that hash blocks may stop earlier,
  /// because they cannot contain sectioning commands.
  int? getStartLineNumber() => null;
}

class HashMarkerEvent extends HashEvent {
  // Line number of first line in block that gets hashed.
  int startLineNumber;

  // Highest possible number of first line after block that gets
  // hashed (where the next \LMHash{} occurs).  Note that this value
  // is not known initially (because that line has not yet been
  // reached), so [endLineNumber] will be initialized in a separate
  // scan.  Also note that the block may end earlier, because a block
  // ends if it would otherwise include a sectioning command.
  int? endLineNumber;

  HashMarkerEvent(this.startLineNumber);

  @override
  void setEndLineNumber(int n) {
    endLineNumber = n;
  }

  @override
  int getStartLineNumber() => startLineNumber;
}

class HashLabelEvent extends HashEvent {
  String labelText;
  HashLabelEvent(this.labelText);
}

class HashAnalyzer {
  // List of kinds of pending (= most recently seen) sectioning command.
  // When updating this list, also update sectioningPrefix below.
  static const PENDING_IS_NONE = 0;
  static const PENDING_IS_SECTION = 1;
  static const PENDING_IS_SUBSECTION = 2;
  static const PENDING_IS_SUBSUBSECTION = 3;
  static const PENDING_IS_PARAGRAPH = 1;

  int lineNumber = 0;
  int pendingSectioning = PENDING_IS_NONE;

  HashAnalyzer();

  void setPendingToSection() {
    pendingSectioning = PENDING_IS_SECTION;
  }

  void setPendingToSubsection() {
    pendingSectioning = PENDING_IS_SUBSECTION;
  }

  void setPendingToSubsubsection() {
    pendingSectioning = PENDING_IS_SUBSUBSECTION;
  }

  void setPendingToParagraph() {
    pendingSectioning = PENDING_IS_PARAGRAPH;
  }

  String sectioningPrefix() {
    switch (pendingSectioning) {
      case PENDING_IS_SECTION:
        return 'sec:';
      case PENDING_IS_SUBSECTION:
        return 'subsec:';
      case PENDING_IS_SUBSUBSECTION:
        return 'subsubsec:';
      case PENDING_IS_NONE:
        throw '\\LMHash{..} should only be used after a sectioning command '
            '(\\section, \\subsection, \\subsubsection, \\paragraph)';
      default:
        // set of PENDING_IS_.. was extended, but updates here omitted
        throw 'Bug, please report to eernst@';
    }
  }

  HashEvent? analyze(String line) {
    var currentLineNumber = lineNumber++;
    if (isHashMarker(line)) {
      return HashMarkerEvent(currentLineNumber);
    } else if (isHashLabel(line)) {
      var labelText = sectioningPrefix() + extractHashLabel(line);
      return HashLabelEvent(labelText);
    } else {
      // No events to emit, but we may need to note state changes
      if (isSectionCommand(line)) {
        setPendingToSection();
      } else if (isSubsectionCommand(line)) {
        setPendingToSubsection();
      } else if (isSubsubsectionCommand(line)) {
        setPendingToSubsubsection();
      } else if (isParagraphCommand(line)) {
        setPendingToParagraph();
      } else {
        // No state changes.
      }
      return null;
    }
  }
}

List<HashEvent> findHashEvents(List<String> lines) {
  // Create the list of events, omitting endLineNumbers.
  var events = findEvents(lines, HashAnalyzer());
  // Set the endLineNumbers.
  var currentEndLineNumber = lines.length;
  for (var event in events.reversed) {
    event.setEndLineNumber(currentEndLineNumber);
    var nextEndLineNumber = event.getStartLineNumber();
    if (nextEndLineNumber != null) currentEndLineNumber = nextEndLineNumber;
  }
  return events;
}

// ----------------------------------------------------------------------
// Removal of non-normative elements of the text (rationale, commentary).

/// Returns [line] without the command [cmdName] (based on a match
/// on "\\cmdName\s*{..}") starting at [startIndex]; note that it is
/// assumed but not checked that [line] contains "\\cmdType\s*{..",
/// and note that the end of the {..} block is found via brace matching
/// (i.e., nested {..} blocks are handled), but it may break if '{' is
/// made an active character etc.etc.
String removeCommand(String line, String cmdName, int startIndex) {
  const BACKSLASH = 92; // char code for '\\'.
  const BRACE_BEGIN = 123; // char code for '{'.
  const BRACE_END = 125; // char code for '}'.

  var blockStartIndex = startIndex + cmdName.length + 1;
  while (blockStartIndex < line.length &&
      line.codeUnitAt(blockStartIndex) != BRACE_BEGIN) {
    blockStartIndex++;
  }
  blockStartIndex++;
  if (blockStartIndex > line.length) {
    throw 'Bug, please report to eernst@';
  }
  // [blockStartIndex] has index just after '{'.

  var afterEscape = false; // Is true iff [index] is just after '{'.
  var braceLevel = 1; // Have seen so many '{'s minus so many '}'s.

  for (var index = blockStartIndex; index < line.length; index++) {
    switch (line.codeUnitAt(index)) {
      case BRACE_BEGIN:
        if (afterEscape) {
          afterEscape = false;
        } else {
          braceLevel++;
        }
        break;
      case BRACE_END:
        if (afterEscape) {
          afterEscape = false;
        } else {
          braceLevel--;
        }
        break;
      case BACKSLASH:
        afterEscape = true;
        break;
      default:
        afterEscape = false;
    }
    if (braceLevel == 0) {
      return line.substring(0, startIndex) + line.substring(index + 1);
    }
  }
  // Removal failed; we consider this to mean that the input is ill-formed.
  throw 'Unmatched braces';
}

final commentaryRE = RegExp(r'\\commentary\s*\{');
final rationaleRE = RegExp(r'\\rationale\s*\{');

/// Removes {}-balanced '\commentary{..}' commands from [line].
String removeCommentary(String line) {
  var match = commentaryRE.firstMatch(line);
  if (match == null) return line;
  return removeCommentary(removeCommand(line, r'commentary', match.start));
}

/// Removes {}-balanced '\rationale{..}' commands from [line].
String removeRationale(String line) {
  var match = rationaleRE.firstMatch(line);
  if (match == null) return line;
  return removeRationale(removeCommand(line, r'rationale', match.start));
}

/// Removes {}-balanced '\commentary{..}' and '\rationale{..}'
/// commands from [line], then normalizes its white-space.
String simplifyLine(String line) {
  var simplerLine = removeCommentary(line);
  simplerLine = removeRationale(simplerLine);
  simplerLine = normalizeWhitespace(simplerLine);
  return simplerLine;
}

// ----------------------------------------------------------------------
// Recognition of line blocks, insertion of block hash into \LMHash{}.

final latexArgumentRE = RegExp(r'\{.*\}');

String cleanupLine(String line) =>
    cutRegexp(line, commentRE, startOffset: 1).trimRight();

/// Returns concatenation of all lines from [startIndex] in [lines] until
/// a hash block terminator is encountered or [nextIndex] reached (if so,
/// the line lines[nextIndex] itself is not included); each line is cleaned
/// up using [cleanupLine], and " " is inserted between the lines gathered.
String gatherLines(List<String> lines, int startIndex, int nextIndex) => lines
    .getRange(startIndex, nextIndex)
    .takeWhile(isntHashBlockTerminator)
    .map(cleanupLine)
    .join(' ');

/// Computes the hash value for the line block starting at [startIndex]
/// in [lines], stopping just before [nextIndex].  SIDE EFFECT:
/// Outputs the simplified text and its hash value to [listSink].
List<int> computeHashValue(
    List<String> lines, int startIndex, int nextIndex, IOSink listSink) {
  final gatheredLine = gatherLines(lines, startIndex, nextIndex);
  final simplifiedLine = simplifyLine(gatheredLine);
  listSink.write('  % $simplifiedLine\n');
  var digest = sha1.convert(utf8.encode(simplifiedLine));
  return digest.bytes;
}

String computeHashString(
        List<String> lines, int startIndex, int nextIndex, IOSink listSink) =>
    hex.encode(computeHashValue(lines, startIndex, nextIndex, listSink));

/// Computes and adds hashes to \LMHash{} lines in [lines] (which must be on the
/// line numbers specified in [hashEvents]), and emits sectioning markers and
/// hash values to [listSink], along with "comments" containing the simplified
/// text (using the format `'  % <text>'`, where the text is one, long line, for
/// easy grepping etc.).
void addHashMarks(
    List<String> lines, List<HashEvent> hashEvents, IOSink listSink) {
  for (var hashEvent in hashEvents) {
    if (hashEvent is HashMarkerEvent) {
      var start = hashEvent.startLineNumber;
      var end = hashEvent.endLineNumber;
      final hashValue = computeHashString(lines, start + 1, end!, listSink);
      lines[start] = lines[start].replaceAll(latexArgumentRE, '{$hashValue}');
      listSink.write('  $hashValue\n');
    } else if (hashEvent is HashLabelEvent) {
      listSink.write('${hashEvent.labelText}\n');
    }
  }
}

/// Transforms LaTeX input to LaTeX output plus hash value list file.
void main(List<String> args) {
  if (args.length != 3) {
    print('Usage: addlatexhash.dart <input-file> <output-file> <list-file>');
    throw 'Received ${args.length} arguments, expected three';
  }

  // Get LaTeX source.
  var inputFile = File(args[0]);
  assert(inputFile.existsSync());
  var lines = inputFile.readAsLinesSync();

  // Will hold LaTeX source with normalized spacing etc., plus hash values.
  var outputFile = File(args[1]);

  // Will hold hierarchical list of hash values.
  var listFile = File(args[2]);
  var listSink = listFile.openWrite();

  // Perform single-line normalization.
  var inDartCode = false;
  var normalizedLines = <String>[];

  for (var line in lines) {
    if (sispIsDartBegin(line)) {
      inDartCode = true;
    } else if (sispIsDartEnd(line)) {
      inDartCode = false;
    }
    if (inDartCode) {
      normalizedLines.add(sispNormalize('$line\n'));
    } else {
      normalizedLines.add(normalize('$line\n'));
    }
  }

  // Perform multi-line normalization.
  normalizedLines = multilineNormalize(normalizedLines);

  // Insert hash values.
  var hashEvents = findHashEvents(normalizedLines);
  addHashMarks(normalizedLines, hashEvents, listSink);

  // Produce/finalize output.
  outputFile.writeAsStringSync(normalizedLines.join());
  listSink.close();
}
