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

import 'dart:math' as math;

import 'package:analysis_server/plugin/edit/fix/fix_core.dart';
import 'package:analysis_server/src/services/correction/strings.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/source/line_info.dart';
import 'package:analyzer/source/source_range.dart';
import 'package:analyzer/src/generated/java_core.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/manifest/manifest_warning_code.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart'
    show SourceChange;
import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
import 'package:html/dom.dart';
import 'package:meta/meta.dart';
import 'package:source_span/source_span.dart';

/// An object used to locate the HTML [Node] associated with a source range.
/// More specifically, it will return the deepest HTML [Node] which completely
/// encompasses the specified range.
class HtmlNodeLocator {
  /// The inclusive start offset of the range used to identify the node.
  int _startOffset = 0;

  /// The inclusive end offset of the range used to identify the node.
  int _endOffset = 0;

  /// Initialize a newly created locator to locate the deepest [Node] for
  /// which `node.offset <= [start]` and `[end] < node.end`.
  ///
  /// If the [end] offset is not provided, then it is considered the same as the
  /// [start] offset.
  HtmlNodeLocator({@required int start, int end})
      : this._startOffset = start,
        this._endOffset = end ?? start;

  /// Search within the given HTML [node] and return the path to the most deeply
  /// nested node that includes the whole target range, or an empty list if no
  /// node was found. The path is represented by all of the elements from the
  /// starting [node] to the most deeply nested node, in reverse order.
  List<Node> searchWithin(Node node) {
    List<Node> path = [];
    _searchWithin(path, node);
    return path;
  }

  void _searchWithin(List<Node> path, Node node) {
    FileSpan span = node.sourceSpan;
    if (span.start.offset > _endOffset || span.end.offset < _startOffset) {
      return;
    }
    for (Element element in node.children) {
      _searchWithin(path, element);
      if (path.isNotEmpty) {
        path.add(node);
        return;
      }
    }
    path.add(node);
  }
}

/// The generator used to generate fixes in Android manifest files.
class ManifestFixGenerator {
  final AnalysisError error;

  final int errorOffset;

  final int errorLength;

  final String content;

  final DocumentFragment document;

  final LineInfo lineInfo;

  final List<Fix> fixes = <Fix>[];

  List<Node> coveringNodePath;

  ManifestFixGenerator(this.error, this.content, this.document)
      : errorOffset = error.offset,
        errorLength = error.length,
        lineInfo = new LineInfo.fromContent(content);

  /// Return the absolute, normalized path to the file in which the error was
  /// reported.
  String get file => error.source.fullName;

  /// Return the list of fixes that apply to the error being fixed.
  Future<List<Fix>> computeFixes() async {
    HtmlNodeLocator locator = new HtmlNodeLocator(
        start: errorOffset, end: errorOffset + errorLength - 1);
    coveringNodePath = locator.searchWithin(document);
    if (coveringNodePath.isEmpty) {
      return fixes;
    }

    ErrorCode errorCode = error.errorCode;
    if (errorCode == ManifestWarningCode.UNSUPPORTED_CHROME_OS_HARDWARE) {
    } else if (errorCode ==
        ManifestWarningCode.PERMISSION_IMPLIES_UNSUPPORTED_HARDWARE) {
    } else if (errorCode ==
        ManifestWarningCode.CAMERA_PERMISSIONS_INCOMPATIBLE) {}
    return fixes;
  }

  /// Add a fix whose edits were built by the [builder] that has the given
  /// [kind]. If [args] are provided, they will be used to fill in the message
  /// for the fix.
  // ignore: unused_element
  void _addFixFromBuilder(ChangeBuilder builder, FixKind kind,
      {List args = null}) {
    SourceChange change = builder.sourceChange;
    if (change.edits.isEmpty) {
      return;
    }
    change.message = formatList(kind.message, args);
    fixes.add(new Fix(kind, change));
  }

  // ignore: unused_element
  int _firstNonWhitespaceBefore(int offset) {
    while (offset > 0 && isWhitespace(content.codeUnitAt(offset - 1))) {
      offset--;
    }
    return offset;
  }

  // ignore: unused_element
  SourceRange _lines(int start, int end) {
    CharacterLocation startLocation = lineInfo.getLocation(start);
    int startOffset = lineInfo.getOffsetOfLine(startLocation.lineNumber - 1);
    CharacterLocation endLocation = lineInfo.getLocation(end);
    int endOffset = lineInfo.getOffsetOfLine(
        math.min(endLocation.lineNumber, lineInfo.lineCount - 1));
    return new SourceRange(startOffset, endOffset - startOffset);
  }
}
