// Copyright (c) 2020, 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.

// Explicitly opt out this file from null safety, for build reasons, inside
// Google.
// @dart=2.9

import 'dart:async';
import 'dart:convert';
import 'dart:html';

import 'package:nnbd_migration/src/front_end/web/edit_details.dart';
import 'package:nnbd_migration/src/front_end/web/file_details.dart';
import 'package:nnbd_migration/src/front_end/web/navigation_tree.dart';
import 'package:nnbd_migration/src/hint_action.dart';
import 'package:path/path.dart' as _p;

import 'highlight_js.dart';

// TODO(devoncarew): Fix the issue where we can't load source maps.

// TODO(devoncarew): Include a favicon.

void main() {
  document.addEventListener('DOMContentLoaded', (event) {
    var path = window.location.pathname;
    var offset = getOffset(window.location.href);
    var lineNumber = getLine(window.location.href);
    loadNavigationTree();
    if (path != '/' && path != rootPath) {
      // TODO(srawlins): replaceState?
      loadFile(path, offset, lineNumber, true, callback: () {
        pushState(path, offset, lineNumber);
      });
    }

    final applyMigrationButton = document.querySelector('.apply-migration');
    applyMigrationButton.onClick.listen((event) {
      if (window.confirm(
          "This will apply the changes you've previewed to your working "
          'directory. It is recommended you commit any changes you made before '
          'doing this.')) {
        var navigationTreeJson = [
          for (var entity in navigationTree) entity.toJson()
        ];
        doPost('/apply-migration', {'navigationTree': navigationTreeJson})
            .then((xhr) {
          document.body.classes
            ..remove('proposed')
            ..add('applied');
        }).catchError((e, st) {
          handleError('Could not apply migration', e, st);
        });
      }
    });

    final rerunMigrationButton = document.querySelector('.rerun-migration');
    rerunMigrationButton.onClick.listen((event) async {
      try {
        document.body.classes..add('rerunning');
        var response = await doPost('/rerun-migration');
        if (response['success'] as bool) {
          window.location.reload();
        } else {
          handleRerunFailure(response['errors'] as List<Object>);
        }
      } catch (e, st) {
        handleError('Failed to rerun migration', e, st);
      } finally {
        document.body.classes.remove('rerunning');
      }
    });

    final reportProblemButton = document.querySelector('.report-problem');
    reportProblemButton.onClick.listen((_) {
      window.open(getGitHubProblemUri().toString(), 'report-problem');
    });

    document.querySelector('.popup-pane .close').onClick.listen(
        (_) => document.querySelector('.popup-pane').style.display = 'none');

    migrateUnitStatusIcon.onClick.listen((MouseEvent event) {
      var unitPath = unitName.innerText;
      var unitNavItem = document
          .querySelector('.nav-panel [data-name*="$unitPath"]')
          .parentNode as Element;
      var statusIcon = unitNavItem.querySelector('.status-icon');
      var entity = navigationTree.find(unitPath);
      if (entity is NavigationTreeFileNode &&
          entity.migrationStatusCanBeChanged) {
        toggleFileMigrationStatus(entity);
        updateIconsForNode(statusIcon, entity);
        updateParentIcons(unitNavItem, entity);
      }
    });
  });

  window.addEventListener('popstate', (event) {
    var path = window.location.pathname;
    var offset = getOffset(window.location.href);
    var lineNumber = getLine(window.location.href);
    if (path.length > 1) {
      loadFile(path, offset, lineNumber, false);
    } else {
      // Blank out the page, for the index screen.
      writeCodeAndRegions(path, FileDetails.empty(), true);
      updatePage('&nbsp;', null);
    }
  });
}

/// Returns the "authToken" query parameter value of the current location.
// TODO(srawlins): This feels a little fragile, as the user can accidentally
//  change/remove this text, and break their session. Normally auth tokens are
//  stored in cookies, but there is no authentication step during which the
//  server would attach such a token to cookies. We could do a little step where
//  the first request to the server with the token is considered
//  "authentication", and we subsequently store the token in cookies thereafter.
final String authToken =
    Uri.parse(window.location.href).queryParameters['authToken'];

final Element editListElement =
    document.querySelector('.edit-list .panel-content');

final Element editPanel = document.querySelector('.edit-panel .panel-content');

final Element footerPanel = document.querySelector('footer');

final Element headerPanel = document.querySelector('header');

final Element unitName = document.querySelector('#unit-name');

final Element migrateUnitStatusIconLabel =
    document.querySelector('#migrate-unit-status-icon-label');

final Element migrateUnitStatusIcon =
    document.querySelector('#migrate-unit-status-icon');

String get rootPath => querySelector('.root').text.trim();

String get sdkVersion => document.getElementById('sdk-version').text;

List<NavigationTreeNode> /*?*/ navigationTree;

void addArrowClickHandler(Element arrow) {
  var childList = (arrow.parentNode as Element).querySelector(':scope > ul');
  // Animating height from "auto" to "0" is not supported by CSS [1], so all we
  // have are hacks. The `* 2` allows for events in which the list grows in
  // height when resized, with additional text wrapping.
  // [1] https://css-tricks.com/using-css-transitions-auto-dimensions/
  childList.style.maxHeight = '${childList.offsetHeight * 2}px';
  arrow.onClick.listen((MouseEvent event) {
    if (!childList.classes.contains('collapsed')) {
      childList.classes.add('collapsed');
      arrow.classes.add('collapsed');
    } else {
      childList.classes.remove('collapsed');
      arrow.classes.remove('collapsed');
    }
  });
}

void addClickHandlers(String selector, bool clearEditDetails) {
  var parentElement = document.querySelector(selector);

  // Add navigation handlers for navigation links in the source code.
  List<Element> navLinks = parentElement.querySelectorAll('.nav-link');
  navLinks.forEach((link) {
    link.onClick.listen((event) => handleNavLinkClick(event, clearEditDetails));
  });

  List<Element> regions = parentElement.querySelectorAll('.region');
  if (regions.isNotEmpty) {
    var table = parentElement.querySelector('table[data-path]');
    var path = table.dataset['path'];
    regions.forEach((Element anchor) {
      anchor.onClick.listen((event) {
        var offset = int.parse(anchor.dataset['offset']);
        var line = int.parse(anchor.dataset['line']);
        loadAndPopulateEditDetails(path, offset, line);
      });
    });
  }

  List<Element> addHintLinks = parentElement.querySelectorAll('.add-hint-link');
  addHintLinks.forEach((link) {
    link.onClick.listen(handleAddHintLinkClick);
  });
}

/// Creates an icon using a `<span>` element and the Material Icons font.
Element createIcon([String name = '']) {
  return document.createElement('span')
    ..classes.add('material-icons')
    ..innerText = name;
}

/// Perform a GET request on the path, return the json decoded response.
///
/// Returns a T so that the various json objects can be requested (lists, maps,
/// etc.).
Future<T> doGet<T>(String path,
        {Map<String, String> queryParameters = const {}}) =>
    doRequest(HttpRequest()
      ..open('GET', pathWithQueryParameters(path, queryParameters), async: true)
      ..setRequestHeader('Content-Type', 'application/json; charset=UTF-8'));

/// Perform a POST request on the path, return the JSON-decoded response.
Future<Map<String, Object>> doPost(String path, [Object body]) => doRequest(
    HttpRequest()
      ..open('POST', pathWithQueryParameters(path, {}), async: true)
      ..setRequestHeader('Content-Type', 'application/json; charset=UTF-8'),
    body);

/// Execute the [HttpRequest], handle its error codes, and return or throw the
/// response.
///
/// This is preferable over helper methods on [HttpRequest] because they ignore
/// the response body on a non-200 code. We want to get that response body in
/// that case, though, because it may be an error response from the server with
/// useful debugging information (stack trace etc).
Future<T> doRequest<T>(HttpRequest xhr, [Object body]) async {
  var completer = Completer<HttpRequest>();
  xhr.onLoad.listen((e) {
    completer.complete(xhr);
  });

  xhr.onError.listen(completer.completeError);

  xhr.send(body == null ? null : jsonEncode(body));

  try {
    await completer.future;
  } catch (e, st) {
    // Handle refused connection and make it user-presentable.
    throw AsyncError('Error reaching migration preview server.', st);
  }

  final json = jsonDecode(xhr.responseText);
  if (xhr.status == 200) {
    // Request OK.
    return json as T;
  } else {
    throw json;
  }
}

/// Returns the URL of the "new issue" form for the SDK repository,
/// pre-populating the title, some labels, using [description], [exception], and
/// [stackTrace] in the body.
Uri getGitHubErrorUri(
        String description, Object exception, Object stackTrace) =>
    Uri.https('github.com', 'dart-lang/sdk/issues/new', {
      'title': 'Customer-reported issue with NNBD migration tool: $description',
      'labels': 'area-analyzer,analyzer-nnbd-migration,type-bug',
      'body': '''
$description

Error: $exception

Please fill in the following:

**Name of package being migrated (if public)**:
**What I was doing when this issue occurred**:
**Is it possible to work around this issue**:
**Has this issue happened before, and if so, how often**:
**Dart SDK version**: $sdkVersion
**Additional details**:

Thanks for filing!

Stacktrace: _auto populated by migration preview tool._

```
$stackTrace
```
''',
    });

/// Returns the URL of the "new issue" form for the SDK repository,
/// pre-populating some labels and a body template.
Uri getGitHubProblemUri() =>
    Uri.https('github.com', 'dart-lang/sdk/issues/new', {
      'title': 'Customer-reported issue with NNBD migration tool',
      'labels': 'area-analyzer,analyzer-nnbd-migration,type-bug',
      'body': '''
#### Steps to reproduce

#### What did you expect to happen?

#### What actually happened?

_Screenshots are appreciated_

**Dart SDK version**: $sdkVersion

Thanks for filing!
''',
    });

int getLine(String location) {
  var str = Uri.parse(location).queryParameters['line'];
  return str == null ? null : int.tryParse(str);
}

int getOffset(String location) {
  var str = Uri.parse(location).queryParameters['offset'];
  return str == null ? null : int.tryParse(str);
}

void handleAddHintLinkClick(MouseEvent event) async {
  var path = (event.currentTarget as Element).getAttribute('href');

  // Don't navigate on link click.
  event.preventDefault();

  try {
    var previousScrollPosition = _getCurrentScrollPosition();
    // Directing the server to produce an edit; request it, then do work with
    // the response.
    await doPost(path);
    await loadFile(window.location.pathname, null, null, false);
    _scrollContentTo(previousScrollPosition);
  } catch (e, st) {
    handleError('Could not add/remove hint', e, st);
  }
}

void handleError(String header, Object exception, Object stackTrace) {
  String subheader;
  if (exception is Map<String, Object> &&
      exception['success'] == false &&
      exception.containsKey('exception') &&
      exception.containsKey('stackTrace')) {
    subheader = exception['exception'] as String;
    stackTrace = exception['stackTrace'];
  } else {
    subheader = exception.toString();
  }
  final popupPane = document.querySelector('.popup-pane');
  popupPane.querySelector('h2').innerText = header;
  popupPane.querySelector('p').innerText = subheader;
  popupPane.querySelector('pre').innerText = stackTrace.toString();
  var bottom = popupPane.querySelector('a.bottom') as AnchorElement;
  bottom
    ..href = getGitHubErrorUri(header, subheader, stackTrace).toString()
    ..style.display = 'initial';
  popupPane..style.display = 'initial';
  logError('$header: $exception', stackTrace);
}

void handleNavLinkClick(MouseEvent event, bool clearEditDetails) {
  Element target = event.currentTarget as Element;
  event.preventDefault();

  var location = target.getAttribute('href');
  var path = _stripQuery(location);

  var offset = getOffset(location);
  var lineNumber = getLine(location);

  if (offset != null) {
    navigate(path, offset, lineNumber, clearEditDetails, callback: () {
      pushState(path, offset, lineNumber);
    });
  } else {
    navigate(path, null, null, clearEditDetails, callback: () {
      pushState(path, null, null);
    });
  }
}

void handleRerunFailure(List<Object> errors) {
  final popupPane = document.querySelector('.popup-pane');
  popupPane.querySelector('h2').innerText = 'Failed to rerun from sources';
  popupPane.querySelector('p').innerText =
      'Sources contain static analysis errors:';
  popupPane.querySelector('pre').innerText = errors.cast<Map>().map((error) {
    return '${error['severity']} - ${error['message']} '
        'at ${error['location']} - (${error['code']})';
  }).join('\n');
  popupPane.querySelector('a.bottom').style.display = 'none';
  popupPane.style.display = 'initial';

  // TODO(srawlins): I think we should lock down the entire web UI, except for
  //  the "Rerun from source" button.
}

void highlightAllCode() {
  document.querySelectorAll('.code').forEach((Element block) {
    hljs.highlightBlock(block);
  });
}

/// Loads the explanation for [region], into the ".panel-content" div.
void loadAndPopulateEditDetails(String path, int offset, int line) async {
  try {
    final responseJson = await doGet<Map<String, Object>>(path,
        queryParameters: {'region': 'region', 'offset': '$offset'});
    var response = EditDetails.fromJson(responseJson);
    populateEditDetails(response);
    pushState(path, offset, line);
    addClickHandlers('.edit-panel .panel-content', false);
  } catch (e, st) {
    handleError('Could not load edit details', e, st);
  }
}

/// Loads the file at [path] from the server, optionally scrolling [offset] into
/// view.
Future<void> loadFile(
  String path,
  int offset,
  int line,
  bool clearEditDetails, {
  VoidCallback callback,
}) async {
  // Handle the case where we're requesting a directory.
  if (!path.endsWith('.dart')) {
    writeCodeAndRegions(path, FileDetails.empty(), clearEditDetails);
    updatePage(path);
    if (callback != null) {
      callback();
    }

    return;
  }

  try {
    // Navigating to another file; request it, then do work with the response.
    final response = await doGet<Map<String, Object>>(path,
        queryParameters: {'inline': 'true'});
    writeCodeAndRegions(path, FileDetails.fromJson(response), clearEditDetails);
    maybeScrollToAndHighlight(offset, line);
    var filePathPart = _stripQuery(path);
    updatePage(filePathPart, offset);
    if (callback != null) {
      callback();
    }
  } catch (e, st) {
    handleError('Could not load dart file $path', e, st);
  }
}

/// Load the navigation tree into the ".nav-tree" div.
void loadNavigationTree() async {
  var path = '/_preview/navigationTree.json';

  // Request the navigation tree, then do work with the response.
  try {
    final response = await doGet<List<Object>>(path);
    var navTree = document.querySelector('.nav-tree');
    navTree.innerHtml = '';
    navigationTree = NavigationTreeNode.listFromJson(response);
    writeNavigationSubtree(navTree, navigationTree,
        enablePartialMigration: true);
  } catch (e, st) {
    handleError('Could not load navigation tree', e, st);
  }
}

void logError(Object e, Object st) {
  window.console.error('$e');
  window.console.error('$st');
}

/// Scroll an element into view if it is not visible.
void maybeScrollIntoView(Element element) {
  var rect = element.getBoundingClientRect();
  // A line of text in the code view is 14px high. Including it here means we
  // only choose to _not_ scroll a line of code into view if the entire line is
  // visible.
  var lineHeight = 14;
  var visibleCeiling = headerPanel.offsetHeight + lineHeight;
  var visibleFloor =
      window.innerHeight - (footerPanel.offsetHeight + lineHeight);
  if (rect.bottom > visibleFloor) {
    element.scrollIntoView();
  } else if (rect.top < visibleCeiling) {
    element.scrollIntoView();
  }
}

/// Scrolls target with id [offset] into view if it is not currently in view.
///
/// Falls back to [lineNumber] if a target with id "o$offset" does not exist.
///
/// Also adds the "target" class, highlighting the target, and the "highlight"
/// class to the entire line on which the target lies.
///
/// If [offset] is null, instead scrolls to the top of the file.
void maybeScrollToAndHighlight(int offset, int lineNumber) {
  Element target;
  Element line;

  if (offset != null) {
    target = document.getElementById('o$offset');
    line = document.querySelector('.line-$lineNumber');
    if (target != null) {
      maybeScrollIntoView(target);
      target.classes.add('target');
    } else if (line != null) {
      // If the target doesn't exist, but the line does, scroll that into view
      // instead.
      maybeScrollIntoView(line.parent);
    }
    if (line != null) {
      (line.parentNode as Element).classes.add('highlight');
    }
  } else {
    // If no offset is given, this is likely a navigation link, and we need to
    // scroll back to the top of the page.
    var lines = document.querySelectorAll('.line-no');
    if (lines.isEmpty) {
      // I don't see how this could happen, but return anyhow.
      return;
    }
    maybeScrollIntoView(lines.first);
  }
}

/// Navigate to [path] and optionally scroll [offset] into view.
///
/// If [callback] is present, it will be called after the server response has
/// been processed, and the content has been updated on the page.
void navigate(
  String path,
  int offset,
  int lineNumber,
  bool clearEditDetails, {
  VoidCallback callback,
}) {
  var currentOffset = getOffset(window.location.href);
  var currentLineNumber = getLine(window.location.href);
  removeHighlight(currentOffset, currentLineNumber);
  if (path == window.location.pathname) {
    // Navigating to same file; just scroll into view.
    maybeScrollToAndHighlight(offset, lineNumber);
    if (callback != null) {
      callback();
    }
  } else {
    loadFile(path, offset, lineNumber, clearEditDetails, callback: callback);
  }
}

/// Returns [path], which may include query parameters, with a new path which
/// adds (or replaces) parameters from [queryParameters].
///
/// Additionally, the "authToken" parameter will be added with the authToken
/// found in the current location.
String pathWithQueryParameters(
    String path, Map<String, String> queryParameters) {
  var uri = Uri.parse(path);
  var mergedQueryParameters = {
    ...uri.queryParameters,
    ...queryParameters,
    'authToken': authToken
  };
  return uri.replace(queryParameters: mergedQueryParameters).toString();
}

String pluralize(int count, String single, {String multiple}) {
  return count == 1 ? single : (multiple ?? '${single}s');
}

void populateEditDetails([EditDetails response]) {
  // Clear out any current edit details.
  editPanel.innerHtml = '';
  if (response == null) {
    Element p = ParagraphElement()
      ..text = 'See details about a proposed edit.'
      ..classes = ['placeholder'];
    editPanel.append(p);
    p.scrollIntoView();
    return;
  }

  var fileDisplayPath = response.displayPath;
  var parentDirectory = _p.dirname(fileDisplayPath);

  // 'Changed ... at foo.dart:12.'
  var explanationMessage = response.explanation;
  var relPath = _p.relative(fileDisplayPath, from: rootPath);
  var line = response.line;
  Element explanation = document.createElement('p');
  editPanel.append(explanation);
  explanation
    ..appendText('$explanationMessage at ')
    ..append(AnchorElement(
        href: pathWithQueryParameters(
            response.uriPath, {'line': line.toString()}))
      ..appendText('$relPath:$line.'));
  explanation.scrollIntoView();
  _populateEditTraces(response, editPanel, parentDirectory);
  _populateEditLinks(response, editPanel);
}

/// Write the contents of the Edit List, from JSON data [editListData].
void populateProposedEdits(
    String path, Map<String, List<EditListItem>> edits, bool clearEditDetails) {
  editListElement.innerHtml = '';

  var editCount = edits.length;
  if (editCount == 0) {
    Element p = document.createElement('p');
    editListElement.append(p);
    p.append(Text('No proposed edits'));
  } else {
    for (var entry in edits.entries) {
      Element p = document.createElement('p');
      editListElement.append(p);
      p.append(Text('${entry.key}:'));

      Element list = document.createElement('ul');
      editListElement.append(list);
      for (var edit in entry.value) {
        Element item = document.createElement('li');
        list.append(item);
        item.classes.add('edit');
        AnchorElement anchor = AnchorElement();
        item.append(anchor);
        anchor.classes.add('edit-link');
        var offset = edit.offset;
        anchor.dataset['offset'] = '$offset';
        var line = edit.line;
        anchor.dataset['line'] = '$line';
        anchor.append(Text('line $line'));
        anchor.setAttribute(
            'href',
            pathWithQueryParameters(window.location.pathname, {
              'line': '$line',
              'offset': '$offset',
            }));
        anchor.onClick.listen((MouseEvent event) {
          event.preventDefault();
          navigate(window.location.pathname, offset, line, true, callback: () {
            pushState(window.location.pathname, offset, line);
          });
          loadAndPopulateEditDetails(path, offset, line);
        });
        item.append(Text(': ${edit.explanation}'));
      }
    }
  }

  if (clearEditDetails) {
    populateEditDetails();
  }
}

void pushState(String path, int offset, int line) {
  var uri = Uri.parse('${window.location.origin}$path');

  var params = {
    if (offset != null) 'offset': '$offset',
    if (line != null) 'line': '$line',
    'authToken': authToken,
  };

  uri = uri.replace(queryParameters: params);
  window.history.pushState({}, '', uri.toString());
}

/// If [path] lies within [root], return the relative path of [path] from [root].
/// Otherwise, return [path].
String relativePath(String path) {
  var root = querySelector('.root').text + '/';
  if (path.startsWith(root)) {
    return path.substring(root.length);
  } else {
    return path;
  }
}

/// Remove highlighting from [offset].
void removeHighlight(int offset, int lineNumber) {
  if (offset != null) {
    var anchor = document.getElementById('o$offset');
    if (anchor != null) {
      anchor.classes.remove('target');
    }
  }
  if (lineNumber != null) {
    var line = document.querySelector('.line-$lineNumber');
    if (line != null) {
      line.parent.classes.remove('highlight');
    }
  }
}

void toggleDirectoryMigrationStatus(NavigationTreeDirectoryNode entity) {
  switch (entity.migrationStatus) {
    case UnitMigrationStatus.alreadyMigrated:
      // This tree cannot be toggled.
      break;
    case UnitMigrationStatus.migrating:
      // At least one child file is 'migrating' (some may be 'already
      // migrated'). Toggle all 'migrating' children to opt out.
      entity.toggleChildrenToOptOut();
      break;
    case UnitMigrationStatus.optingOut:
      // At least one child file is 'opting out' (some may be 'already
      // migrated'). Toggle all 'migrating' children to migrate.
      entity.toggleChildrenToMigrate();
      break;
    case UnitMigrationStatus.indeterminate:
      // At least one child file is 'migrating' and at least one child file is
      // 'opting out' (some may be 'already migrated'). Toggle all 'migrating'
      // children to migrate.
      entity.toggleChildrenToMigrate();
  }
}

void toggleFileMigrationStatus(NavigationTreeFileNode entity) {
  switch (entity.migrationStatus) {
    case UnitMigrationStatus.alreadyMigrated:
      // This file cannot be toggled.
      break;
    case UnitMigrationStatus.migrating:
      entity.migrationStatus = UnitMigrationStatus.optingOut;
      break;
    case UnitMigrationStatus.optingOut:
      entity.migrationStatus = UnitMigrationStatus.migrating;
      break;
    case UnitMigrationStatus.indeterminate:
      throw StateError('File ${entity.path} should not have '
          'indeterminate migration status');
  }
}

/// Updates the navigation [icon] and current file icon according to the current
/// migration status of [entity].
void updateIconsForNode(Element icon, NavigationTreeNode entity) {
  var status = entity.migrationStatus;
  updateIconForStatus(icon, status);
  // Update the status at the top of the file view if [entity] represents the
  // current file.
  var unitPath = unitName.innerText;
  if (entity.path == unitPath) {
    if (entity is NavigationTreeFileNode &&
        !entity.migrationStatusCanBeChanged) {
      icon.classes.add('disabled');
    } else {
      icon.classes.remove('disabled');
    }
    updateIconForStatus(migrateUnitStatusIcon, status);
  }
}

/// Updates [icon] according to [status].
void updateIconForStatus(Element icon, UnitMigrationStatus status) {
  switch (status) {
    case UnitMigrationStatus.alreadyMigrated:
      icon.innerText = 'check_box';
      icon.classes.add('already-migrated');
      icon.classes.add('disabled');
      icon.setAttribute('title', 'Already migrated');
      break;
    case UnitMigrationStatus.migrating:
      icon.innerText = 'check_box';
      icon.classes.remove('opted-out');
      icon.classes.add('migrating');
      icon.setAttribute('title', 'Migrating to null safety');
      break;
    case UnitMigrationStatus.optingOut:
      icon.innerText = 'check_box_outline_blank';
      icon.classes.remove('migrating');
      icon.classes.add('opted-out');
      icon.setAttribute('title', 'Opting out of null safety');
      break;
    default:
      icon.innerText = 'indeterminate_check_box';
      icon.classes.remove('migrating');
      // 'opted-out' is the same style as 'indeterminate'.
      icon.classes.add('opted-out');
      icon.setAttribute(
          'title', "Mixed statuses of 'migrating' and 'opting out'");
      break;
  }
}

/// Update the heading and navigation links.
///
/// Call this after updating page content on a navigation.
void updatePage(String path, [int offset]) {
  path = relativePath(path);
  // Update page heading.
  unitName.text = path;
  // Update navigation styles.
  document.querySelectorAll('.nav-panel .nav-link').forEach((Element link) {
    var name = link.dataset['name'];
    if (name == path) {
      link.classes.add('selected-file');
    } else {
      link.classes.remove('selected-file');
    }
  });
  // Note: navigationTree might not be loaded yet if the user is clicking around
  // fast, so we need to allow for the possibility that `navigationTree` might
  // be `null`.
  var entity = navigationTree?.find(path);
  // Update migration status for files in current migration.
  if (entity == null) {
    migrateUnitStatusIconLabel.classes.remove('visible');
  } else {
    migrateUnitStatusIconLabel.classes.add('visible');
    updateIconForStatus(migrateUnitStatusIcon, entity.migrationStatus);
  }
}

/// Updates the parent icons of [entity] with list item [element] in the
/// navigation tree.
void updateParentIcons(Element element, NavigationTreeNode entity) {
  var parent = entity.parent;
  if (parent != null) {
    var parentElement = (element.parentNode as Element).parentNode as Element;
    var statusIcon = parentElement.querySelector(':scope > .status-icon');
    updateIconsForNode(statusIcon, parent);
    updateParentIcons(parentElement, parent);
  }
}

/// Updates subtree icons for the children [entity] with list item [element].
void updateSubtreeIcons(Element element, NavigationTreeDirectoryNode entity) {
  for (var child in entity.subtree) {
    var childNode = element.querySelector('[data-name*="${child.path}"]');
    if (child is NavigationTreeDirectoryNode) {
      updateSubtreeIcons(childNode, child);
      var childIcon = childNode.querySelector(':scope > .status-icon');
      updateIconsForNode(childIcon, entity);
    } else {
      var childIcon = (childNode.parentNode as Element)
          .querySelector(':scope > .status-icon');
      updateIconsForNode(childIcon, child);
    }
  }
}

/// Load data from [data] into the .code and the .regions divs.
void writeCodeAndRegions(String path, FileDetails data, bool clearEditDetails) {
  var regionsElement = document.querySelector('.regions');
  var codeElement = document.querySelector('.code');

  _PermissiveNodeValidator.setInnerHtml(regionsElement, data.regions);
  _PermissiveNodeValidator.setInnerHtml(codeElement, data.navigationContent);
  populateProposedEdits(path, data.edits, clearEditDetails);

  // highlightAllCode is remarkably slow (about 4 seconds to handle a 300k file
  // on a Pixelbook), so skip it for large files.
  if (data.sourceCode.length < 200000) {
    highlightAllCode();
  }
  addClickHandlers('.code', true);
  addClickHandlers('.regions', true);
}

void writeNavigationSubtree(
    Element parentElement, List<NavigationTreeNode> tree,
    {bool enablePartialMigration = false}) {
  Element ul = document.createElement('ul');
  parentElement.append(ul);
  for (var entity in tree) {
    Element li = document.createElement('li');
    ul.append(li);
    if (entity is NavigationTreeDirectoryNode) {
      li.classes.add('dir');
      li.dataset['name'] = entity.path;
      Element arrow = document.createElement('span');
      li.append(arrow);
      arrow.classes.add('arrow');
      arrow.innerHtml = '&#x25BC;';
      var folderIcon = createIcon('folder_open');
      li.append(folderIcon);
      li.append(Text(entity.name));
      writeNavigationSubtree(li, entity.subtree,
          enablePartialMigration: enablePartialMigration);
      if (enablePartialMigration) {
        var statusIcon = createIcon('indeterminate_check_box')
          ..classes.add('status-icon');
        updateIconsForNode(statusIcon, entity);
        statusIcon.onClick.listen((MouseEvent event) {
          toggleDirectoryMigrationStatus(entity);
          updateSubtreeIcons(li, entity);
          updateIconsForNode(statusIcon, entity);
          updateParentIcons(li, entity);
        });
        li.insertBefore(statusIcon, folderIcon);
      }
      addArrowClickHandler(arrow);
    } else if (entity is NavigationTreeFileNode) {
      if (enablePartialMigration) {
        var statusIcon = createIcon()..classes.add('status-icon');
        if (entity is NavigationTreeFileNode &&
            !entity.migrationStatusCanBeChanged) {
          statusIcon.classes.add('disabled');
        }
        updateIconsForNode(statusIcon, entity);
        if (entity.migrationStatusCanBeChanged) {
          statusIcon.onClick.listen((MouseEvent event) {
            toggleFileMigrationStatus(entity);
            updateIconsForNode(statusIcon, entity);
            updateParentIcons(li, entity);
          });
        }
        li.append(statusIcon);
      }
      li.append(createIcon('insert_drive_file'));
      Element a = document.createElement('a');
      li.append(a);
      a.classes.add('nav-link');
      a.dataset['name'] = entity.path;
      a.setAttribute('href', pathWithQueryParameters(entity.href, {}));
      a.append(Text(entity.name));
      a.onClick.listen((MouseEvent event) => handleNavLinkClick(event, true));
      var editCount = entity.editCount;
      if (editCount > 0) {
        Element editsBadge = document.createElement('span');
        li.append(editsBadge);
        editsBadge.classes.add('edit-count');
        editsBadge.setAttribute(
            'title', '$editCount ${pluralize(editCount, 'proposed edit')}');
        editsBadge.append(Text(editCount.toString()));
      }
    }
  }
}

void _addHintAction(HintAction hintAction, Node drawer, TargetLink link) {
  drawer.append(ButtonElement()
    ..onClick.listen((event) async {
      try {
        var previousScrollPosition = _getCurrentScrollPosition();
        await doPost(
            pathWithQueryParameters('/apply-hint', {}), hintAction.toJson());
        var path = _stripQuery(link.href);
        await loadFile(path, null, link.line, false);
        document.body.classes.add('needs-rerun');
        _scrollContentTo(previousScrollPosition);
      } catch (e, st) {
        handleError('Could not apply hint', e, st);
      }
    })
    ..appendText(hintAction.kind.description));
}

AnchorElement _aElementForLink(TargetLink link) {
  var targetLine = link.line;
  AnchorElement a = AnchorElement();
  a.append(Text('${link.path}:$targetLine'));
  a.setAttribute('href', link.href);
  a.classes.add('nav-link');
  return a;
}

int _getCurrentScrollPosition() => document.querySelector('.content').scrollTop;

void _populateEditLinks(EditDetails response, Element editPanel) {
  if (response.edits == null) {
    return;
  }

  var subheading = editPanel.append(document.createElement('p'));
  subheading.append(document.createElement('span')
    ..classes = ['type-description']
    ..append(Text('Actions')));
  subheading.append(Text(':'));

  Element editParagraph = document.createElement('p');
  editPanel.append(editParagraph);
  for (var edit in response.edits) {
    Element a = document.createElement('a');
    editParagraph.append(a);
    a.append(Text(edit.description));
    a.setAttribute('href', edit.href);
    a.classes = ['add-hint-link', 'before-apply', 'button'];
  }
}

void _populateEditTraces(
    EditDetails response, Element editPanel, String parentDirectory) {
  for (var trace in response.traces) {
    var traceParagraph =
        editPanel.append(document.createElement('p')..classes = ['trace']);
    traceParagraph.append(document.createElement('span')
      ..classes = ['type-description']
      ..append(Text(trace.description)));
    traceParagraph.append(Text(':'));
    var ul = traceParagraph
        .append(document.createElement('ul')..classes = ['trace']);
    for (var entry in trace.entries) {
      Element li = document.createElement('li');
      ul.append(li);
      li.append(document.createElement('span')
        ..classes = ['function']
        ..appendTextWithBreaks(entry.function ?? 'unknown'));
      var link = entry.link;
      if (link != null) {
        li.append(Text(' ('));
        li.append(_aElementForLink(link));
        li.append(Text(')'));
      }
      li.append(Text(': '));
      li.appendTextWithBreaks(entry.description ?? 'unknown');

      if (entry.hintActions.isNotEmpty) {
        var drawer = li.append(
            document.createElement('p')..classes = ['drawer', 'before-apply']);
        for (final hintAction in entry.hintActions) {
          _addHintAction(hintAction, drawer, link);
        }
      }
    }
  }
}

void _scrollContentTo(int top) =>
    document.querySelector('.content').scrollTop = top;

String _stripQuery(String path) =>
    path.contains('?') ? path.substring(0, path.indexOf('?')) : path;

class _PermissiveNodeValidator implements NodeValidator {
  static _PermissiveNodeValidator instance = _PermissiveNodeValidator();

  @override
  bool allowsAttribute(Element element, String attributeName, String value) {
    return true;
  }

  @override
  bool allowsElement(Element element) {
    return true;
  }

  static void setInnerHtml(Element element, String html) {
    element.setInnerHtml(html, validator: instance);
  }
}

/// An extension on Element that fits into cascades.
extension on Element {
  /// Append [text] to this, inserting a word break before each '.' character.
  void appendTextWithBreaks(String text) {
    var textParts = text.split('.');
    append(Text(textParts.first));
    for (var substring in textParts.skip(1)) {
      // Replace the '.' with a zero-width space and a '.'.
      appendHtml('&#8203;.');
      append(Text(substring));
    }
  }
}

extension on List<NavigationTreeNode> {
  /// Finds the node with path equal to [path], recursively, or `null`.
  NavigationTreeNode find(String path) {
    for (var node in this) {
      if (node is NavigationTreeDirectoryNode) {
        var foundInSubtree = node.subtree.find(path);
        if (foundInSubtree != null) return foundInSubtree;
      } else {
        assert(node is NavigationTreeFileNode);
        if (node.path == path) return node;
      }
    }
    return null;
  }
}
