// 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.

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

import 'package:nnbd_migration/instrumentation.dart';
import 'package:nnbd_migration/src/front_end/migration_info.dart';
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: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.')) {
        doPost('/apply-migration').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) {
        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;

/*late final*/ 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) {
      var tableElement = document.querySelector('table[data-path]');
      var parentPath = tableElement.dataset['path'];
      handleNavLinkClick(event, clearEditDetails, relativeTo: parentPath);
    });
  });

  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, {
  String relativeTo,
}) {
  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: false);
  } catch (e, st) {
    handleError('Could not load navigation tree', e, st);
  }
}

void logError(e, 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) {
  updateIconForStatus(icon, entity.migrationStatus);
  // Update the status at the top of the file view if [entity] represents the
  // current file.
  var unitPath = unitName.innerText;
  if (entity.path == unitPath) {
    updateIconForStatus(migrateUnitStatusIcon, entity.migrationStatus);
  }
}

/// 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.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');
    }
  });
  migrateUnitStatusIconLabel.classes.add('visible');
}

/// 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');
        updateIconsForNode(statusIcon, entity);
        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;
  }
}
