// 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 'package:analyzer/error/error.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/manifest/charcodes.dart';
import 'package:analyzer/src/manifest/manifest_values.dart';
import 'package:analyzer/src/manifest/manifest_warning_code.dart';
import 'package:collection/collection.dart';
import 'package:meta/meta.dart';
import 'package:source_span/source_span.dart';

/// A rudimentary parser for Android Manifest files.
///
/// Android Manifest files are written in XML. In order to validate an Android
/// Manifest file, however, we do not need to parse or retain each element. This
/// parser understands which elements are relevant to manifest validation.
/// This parser does not validate the XML, and if it encounters an error while
/// parsing, no exception is thrown. Instead, a parse result with
/// [ParseResult.error] is returned.
///
/// This parser does not understand
///
/// * CDATA sections (https://www.w3.org/TR/xml/#sec-cdata-sect),
/// * element type declarations (https://www.w3.org/TR/xml/#elemdecls),
/// * attribute list declarations (https://www.w3.org/TR/xml/#attdecls),
/// * conditional sections (https://www.w3.org/TR/xml/#sec-condition-sect),
/// * entity declarations (https://www.w3.org/TR/xml/#sec-entity-decl),
/// * notation declarations (https://www.w3.org/TR/xml/#Notations).
///
/// This parser does not replace character or entity references
/// (https://www.w3.org/TR/xml/#sec-references).
class ManifestParser {
  /// Elements which are relevant to manifest validation.
  static const List<String> _relevantElements = [
    ACTIVITY_TAG,
    APPLICATION_TAG,
    MANIFEST_TAG,
    USES_FEATURE_TAG,
    USES_PERMISSION_TAG
  ];

  /// The text of the Android Manifest file.
  final String content;

  /// The source file representing the Android Manifest file, for source span
  /// purposes.
  final SourceFile sourceFile;

  /// The current offset in the source file.
  int _pos;

  ManifestParser(this.content, Uri uri)
      : sourceFile = SourceFile.fromString(content, url: uri),
        _pos = 0;

  /// Whether the current character is a tag-closing character (">").
  bool get _isClosing =>
      _pos < content.length && content.codeUnitAt(_pos) == $gt;

  /// Whether the current character and the following two characters make a
  /// comment closing ("-->").
  bool get _isCommentClosing =>
      _pos + 2 < content.length &&
      content.codeUnitAt(_pos) == $dash &&
      content.codeUnitAt(_pos + 1) == $dash &&
      content.codeUnitAt(_pos + 2) == $gt;

  /// Whether the following three characters make a comment opening ("<!--").
  bool get _isCommentOpening =>
      _pos + 3 < content.length &&
      content.codeUnitAt(_pos + 1) == $exclamation &&
      content.codeUnitAt(_pos + 2) == $dash &&
      content.codeUnitAt(_pos + 3) == $dash;

  /// Whether the following character makes a comment opening ("<!").
  bool get _isDeclarationOpening =>
      _pos + 1 < content.length && content.codeUnitAt(_pos + 1) == $exclamation;

  /// Whether the current character and the following character make a
  /// two-character closing.
  ///
  /// The "/>" and "?>" closings each represent an empty element.
  bool get _isTwoCharClosing =>
      _pos + 1 < content.length &&
      (content.codeUnitAt(_pos) == $question ||
          content.codeUnitAt(_pos) == $slash) &&
      content.codeUnitAt(_pos + 1) == $gt;

  bool get _isWhitespace {
    var char = content.codeUnitAt(_pos);
    return char == $space || char == $tab || char == $lf || char == $cr;
  }

  /// Parses an XML tag into a [ParseTagResult].
  ParseTagResult parseXmlTag() {
    // Walk until we find a tag.
    while (_pos < content.length && content.codeUnitAt(_pos) != $lt) {
      _pos++;
    }
    if (_pos >= content.length) {
      return ParseTagResult.eof;
    }
    if (_isCommentOpening) {
      return _parseComment();
    }
    if (_isDeclarationOpening) {
      return _parseDeclaration();
    }

    return _parseNormalTag();
  }

  /// Returns whether [name] represents an element that is relevant to manifest
  /// validation.
  bool _isRelevantElement(String name) => _relevantElements.contains(name);

  /// Parses any whitespace, returning `null` when non-whitespace is parsed.
  ParseResult? _parseAnyWhitespace() {
    if (_pos >= content.length) {
      return ParseResult.error;
    }

    while (_isWhitespace) {
      _pos++;
      if (_pos >= content.length) {
        return ParseResult.error;
      }
    }
    return null;
  }

  /// Parses an attribute.
  ParseAttributeResult _parseAttribute(bool isRelevant) {
    var attributes = <String, _XmlAttribute>{};
    bool isEmptyElement;

    while (true) {
      if (_pos >= content.length) {
        return ParseAttributeResult.error;
      }
      var char = content.codeUnitAt(_pos);

      // In each loop, [_pos] must either be whitespace, ">", "/>", or "?>" to
      // be valid.
      if (_isClosing) {
        isEmptyElement = false;
        break;
      } else if (_isTwoCharClosing) {
        isEmptyElement = true;
        _pos++;
        break;
      } else if (!_isWhitespace) {
        return ParseAttributeResult.error;
      }

      var parsedWhitespaceResult = _parseAnyWhitespace();
      if (parsedWhitespaceResult == ParseResult.error) {
        return ParseAttributeResult.error;
      }

      if (_isClosing) {
        isEmptyElement = false;
        break;
      } else if (_isTwoCharClosing) {
        isEmptyElement = true;
        _pos++;
        break;
      }

      // Parse attribute name.
      var attributeNamePos = _pos;
      late String attributeName;
      _pos++;
      if (_pos >= content.length) {
        return ParseAttributeResult.error;
      }

      while ((char = content.codeUnitAt(_pos)) != $equal) {
        if (_isWhitespace || _isClosing || _isTwoCharClosing) {
          // An attribute without a value, while allowed in HTML, is not allowed
          // in XML.
          return ParseAttributeResult.error;
        }
        _pos++;
        if (_pos >= content.length) {
          return ParseAttributeResult.error;
        }
      }

      if (isRelevant) {
        attributeName = content.substring(attributeNamePos, _pos).toLowerCase();
      }
      _pos++; // Walk past "=".
      if (_pos >= content.length) {
        return ParseAttributeResult.error;
      }

      // Parse attribute value.
      int quote;
      char = content.codeUnitAt(_pos);
      if (char == $apostrophe || char == $quote) {
        quote = char;
        _pos++;
      } else {
        // An attribute name, followed by "=", followed by ">" is an error.
        return ParseAttributeResult.error;
      }
      int attributeValuePos = _pos;

      while ((char = content.codeUnitAt(_pos)) != quote) {
        _pos++;
        if (_pos >= content.length) {
          return ParseAttributeResult.error;
        }
      }

      if (isRelevant) {
        var attributeValue = content.substring(attributeValuePos, _pos);
        var sourceSpan = sourceFile.span(attributeNamePos, _pos);
        attributes[attributeName] =
            _XmlAttribute(attributeName, attributeValue, sourceSpan);
      }
      _pos++;
    }

    var parseResult = isEmptyElement
        ? ParseResult.attributesWithEmptyElementClose
        : ParseResult.attributesWithTagClose;

    return ParseAttributeResult(parseResult, attributes);
  }

  /// Parses a comment tag, as per https://www.w3.org/TR/xml/#sec-comments.
  ParseTagResult _parseComment() {
    // Walk past "<!--"
    _pos += 4;
    if (_pos >= content.length) {
      return ParseTagResult.error;
    }
    while (!_isCommentClosing) {
      _pos++;
      if (_pos >= content.length) {
        return ParseTagResult.error;
      }
    }
    _pos += 2;

    return ParseTagResult(ParseResult.element, null);
  }

  /// Parses a general declaration.
  ///
  /// Declarations are not processed or stored. The parser just intends to read
  /// the tag and return.
  ParseTagResult _parseDeclaration() {
    // Walk past "<!"
    _pos += 2;
    if (_pos >= content.length) {
      return ParseTagResult.error;
    }
    while (!_isClosing) {
      _pos++;
      if (_pos >= content.length) {
        return ParseTagResult.error;
      }
    }

    return ParseTagResult(ParseResult.element, null);
  }

  /// Parses a normal tag starting with an '<' character at the current
  /// position.
  ParseTagResult _parseNormalTag() {
    var startPos = _pos;
    _pos++;

    if (_pos >= content.length) {
      return ParseTagResult.error;
    }

    if (_isWhitespace) {
      // A tag cannot begin with whitespace.
      return ParseTagResult.error;
    }

    var isEndTag = content.codeUnitAt(_pos) == $slash;
    if (isEndTag) _pos++;
    var tagClosingState = _TagClosingState.notClosed;

    // Parse name.
    var namePos = _pos;
    late String name;

    while (!_isClosing && !_isTwoCharClosing && !_isWhitespace) {
      _pos++;
      if (_pos >= content.length) {
        return ParseTagResult.error;
      }
    }

    if (_isClosing) {
      // End of tag name, and tag.
      name = content.substring(namePos, _pos).toLowerCase();
      tagClosingState = _TagClosingState.closed;
    } else if (_isTwoCharClosing) {
      // End of tag name, tag, and element.
      name = content.substring(namePos, _pos).toLowerCase();
      tagClosingState = _TagClosingState.closedEmptyElement;
      _pos++;
    } else if (_isWhitespace) {
      // End of tag name.
      name = content.substring(namePos, _pos).toLowerCase();
    }

    if (isEndTag) {
      var parsedWhitespaceResult = _parseAnyWhitespace();
      if (parsedWhitespaceResult == ParseResult.error) {
        return ParseTagResult.error;
      }
      if (_isClosing) {
        // End tags cannot have attributes.
        return ParseTagResult(
            ParseResult.endTag, _XmlElement(name, {}, [], null));
      } else {
        return ParseTagResult.error;
      }
    }

    var isRelevant = _isRelevantElement(name);

    Map<String, _XmlAttribute> attributes;
    bool isEmptyElement;
    if (tagClosingState == _TagClosingState.notClosed) {
      // Have not parsed the tag close yet; parse attributes.
      var attributeResult = _parseAttribute(isRelevant);
      var parseResult = attributeResult.parseResult;
      if (parseResult == ParseResult.error) {
        return ParseTagResult.error;
      }
      attributes = attributeResult.attributes!;
      isEmptyElement =
          parseResult == ParseResult.attributesWithEmptyElementClose;
    } else {
      attributes = {};
      isEmptyElement = tagClosingState == _TagClosingState.closedEmptyElement;
    }
    if (name.startsWith('!')) {
      // Declarations (generally beginning with '!', do not require end tags.
      isEmptyElement = true;
    }

    var children = <_XmlElement>[];
    if (!isEmptyElement) {
      ParseTagResult child;
      _pos++;
      // Parse any children, and end tag.
      while ((child = parseXmlTag()).parseResult != ParseResult.endTag) {
        if (child == ParseTagResult.eof || child == ParseTagResult.error) {
          return child;
        }
        if (child.element == null) {
          // Don't store an irrelevant element.
          continue;
        }
        children.add(child.element!);
        _pos++;
      }
    }

    // Finished parsing start tag.
    if (isRelevant) {
      var sourceSpan = sourceFile.span(startPos, _pos);
      return ParseTagResult(ParseResult.relevantElement,
          _XmlElement(name, attributes, children, sourceSpan));
    } else {
      // Discard all parsed children. This requires the notion that all relevant
      // tags are direct children of other relevant tags.
      return ParseTagResult(ParseResult.element, null);
    }
  }
}

class ManifestValidator {
  /// The source representing the file being validated.
  final Source source;

  /// Initialize a newly create validator to validate the content of the given
  /// [source].
  ManifestValidator(this.source);

  /// Validate the [contents] of the Android Manifest file.
  List<AnalysisError> validate(String content, bool checkManifest) {
    // TODO(srawlins): Simplify [checkManifest] notion. Why call the method if
    //  the caller always knows whether it should just return empty?
    if (!checkManifest) return [];

    RecordingErrorListener recorder = RecordingErrorListener();
    ErrorReporter reporter = ErrorReporter(
      recorder,
      source,
      isNonNullableByDefault: false,
    );

    var xmlParser = ManifestParser(content, source.uri);

    _checkManifestTag(xmlParser, reporter);
    return recorder.errors;
  }

  void _checkManifestTag(ManifestParser parser, ErrorReporter reporter) {
    ParseTagResult parseTagResult;
    while (
        (parseTagResult = parser.parseXmlTag()).element?.name != MANIFEST_TAG) {
      if (parseTagResult == ParseTagResult.eof ||
          parseTagResult == ParseTagResult.error) {
        return;
      }
    }

    var manifestElement = parseTagResult.element!;
    var features =
        manifestElement.children.where((e) => e.name == USES_FEATURE_TAG);
    var permissions =
        manifestElement.children.where((e) => e.name == USES_PERMISSION_TAG);
    _validateTouchScreenFeature(features, manifestElement, reporter);
    _validateFeatures(features, reporter);
    _validatePermissions(permissions, features, reporter);

    var application = manifestElement.children
        .firstWhereOrNull((e) => e.name == APPLICATION_TAG);
    if (application != null) {
      for (var activity
          in application.children.where((e) => e.name == ACTIVITY_TAG)) {
        _validateActivity(activity, reporter);
      }
    }
  }

  bool _hasFeatureCamera(Iterable<_XmlElement> features) => features
      .any((f) => f.attributes[ANDROID_NAME]?.value == HARDWARE_FEATURE_CAMERA);

  bool _hasFeatureCameraAutoFocus(Iterable<_XmlElement> features) =>
      features.any((f) =>
          f.attributes[ANDROID_NAME]?.value ==
          HARDWARE_FEATURE_CAMERA_AUTOFOCUS);

  /// Report an error for the given node.
  void _reportErrorForNode(ErrorReporter reporter, _XmlElement node,
      String? key, ErrorCode errorCode,
      [List<Object>? arguments]) {
    var span =
        key == null ? node.sourceSpan! : node.attributes[key]!.sourceSpan;
    reporter.reportErrorForOffset(
        errorCode, span.start.offset, span.length, arguments);
  }

  /// Validate the 'activity' tags.
  void _validateActivity(_XmlElement activity, ErrorReporter reporter) {
    var attributes = activity.attributes;
    if (attributes.containsKey(ATTRIBUTE_SCREEN_ORIENTATION)) {
      if (UNSUPPORTED_ORIENTATIONS
          .contains(attributes[ATTRIBUTE_SCREEN_ORIENTATION]?.value)) {
        _reportErrorForNode(reporter, activity, ATTRIBUTE_SCREEN_ORIENTATION,
            ManifestWarningCode.SETTING_ORIENTATION_ON_ACTIVITY);
      }
    }
    if (attributes.containsKey(ATTRIBUTE_RESIZEABLE_ACTIVITY)) {
      if (attributes[ATTRIBUTE_RESIZEABLE_ACTIVITY]?.value == 'false') {
        _reportErrorForNode(reporter, activity, ATTRIBUTE_RESIZEABLE_ACTIVITY,
            ManifestWarningCode.NON_RESIZABLE_ACTIVITY);
      }
    }
  }

  /// Validate the `uses-feature` tags.
  void _validateFeatures(
      Iterable<_XmlElement> features, ErrorReporter reporter) {
    var unsupported = features.where((element) => UNSUPPORTED_HARDWARE_FEATURES
        .contains(element.attributes[ANDROID_NAME]?.value));
    for (var element in unsupported) {
      if (!element.attributes.containsKey(ANDROID_REQUIRED)) {
        // Since `unsupported` is the list of elements for which
        // `elements.attributes[ANDROID_NAME]?.value` is contained in
        // [UNSUPPORTED_HARDWARE_FEATURES], which is a list of non-nullable
        // strings, it follows that `element.attributes[ANDROID_NAME]` is
        // non-`null`.
        _reportErrorForNode(
            reporter,
            element,
            ANDROID_NAME,
            ManifestWarningCode.UNSUPPORTED_CHROME_OS_HARDWARE,
            [element.attributes[ANDROID_NAME]!.value]);
      } else if (element.attributes[ANDROID_REQUIRED]?.value == 'true') {
        // Since `unsupported` is the list of elements for which
        // `elements.attributes[ANDROID_NAME]?.value` is contained in
        // [UNSUPPORTED_HARDWARE_FEATURES], which is a list of non-nullable
        // strings, it follows that `element.attributes[ANDROID_NAME]` is
        // non-`null`.
        _reportErrorForNode(
            reporter,
            element,
            ANDROID_NAME,
            ManifestWarningCode.UNSUPPORTED_CHROME_OS_FEATURE,
            [element.attributes[ANDROID_NAME]!.value]);
      }
    }
  }

  /// Validate the `uses-permission` tags.
  void _validatePermissions(Iterable<_XmlElement> permissions,
      Iterable<_XmlElement> features, ErrorReporter reporter) {
    for (var permission in permissions) {
      if (permission.attributes[ANDROID_NAME]?.value ==
          ANDROID_PERMISSION_CAMERA) {
        if (!_hasFeatureCamera(features) ||
            !_hasFeatureCameraAutoFocus(features)) {
          _reportErrorForNode(reporter, permission, ANDROID_NAME,
              ManifestWarningCode.CAMERA_PERMISSIONS_INCOMPATIBLE);
        }
      } else {
        var featureName = getImpliedUnsupportedHardware(
            permission.attributes[ANDROID_NAME]?.value);
        if (featureName != null) {
          _reportErrorForNode(
              reporter,
              permission,
              ANDROID_NAME,
              ManifestWarningCode.PERMISSION_IMPLIES_UNSUPPORTED_HARDWARE,
              [featureName]);
        }
      }
    }
  }

  /// Validate the presence/absence of the touchscreen feature tag.
  void _validateTouchScreenFeature(Iterable<_XmlElement> features,
      _XmlElement manifest, ErrorReporter reporter) {
    var feature = features.firstWhereOrNull((element) =>
        element.attributes[ANDROID_NAME]?.value ==
        HARDWARE_FEATURE_TOUCHSCREEN);
    if (feature != null) {
      if (!feature.attributes.containsKey(ANDROID_REQUIRED)) {
        _reportErrorForNode(
            reporter,
            feature,
            ANDROID_NAME,
            ManifestWarningCode.UNSUPPORTED_CHROME_OS_HARDWARE,
            [HARDWARE_FEATURE_TOUCHSCREEN]);
      } else if (feature.attributes[ANDROID_REQUIRED]?.value == 'true') {
        _reportErrorForNode(
            reporter,
            feature,
            ANDROID_NAME,
            ManifestWarningCode.UNSUPPORTED_CHROME_OS_FEATURE,
            [HARDWARE_FEATURE_TOUCHSCREEN]);
      }
    } else {
      _reportErrorForNode(
          reporter, manifest, null, ManifestWarningCode.NO_TOUCHSCREEN_FEATURE);
    }
  }
}

@visibleForTesting
class ParseAttributeResult {
  static ParseAttributeResult error =
      ParseAttributeResult(ParseResult.error, null);

  final ParseResult parseResult;

  final Map<String, _XmlAttribute>? attributes;

  ParseAttributeResult(this.parseResult, this.attributes);
}

enum ParseResult {
  // Attributes were parsed, followed by a tag close like "/>", signifying an
  // empty element, as per https://www.w3.org/TR/xml/#sec-starttags.
  attributesWithEmptyElementClose,
  // Attributes were parsed, followed by a tag close, ">".
  attributesWithTagClose,
  // A start tag for an irrelevant element was parsed, as per
  // https://www.w3.org/TR/xml/#sec-starttags.
  element,
  // An end tag for an element was parsed, as per
  // https://www.w3.org/TR/xml/#sec-starttags.
  endTag,
  // The content's EOF was parsed.
  eof,
  // An error was encountered.
  error,
  // A relevant element was parsed.
  relevantElement,
}

@visibleForTesting
class ParseTagResult {
  static ParseTagResult eof = ParseTagResult(ParseResult.eof, null);
  static ParseTagResult error = ParseTagResult(ParseResult.error, null);

  final ParseResult parseResult;

  final _XmlElement? element;

  ParseTagResult(this.parseResult, this.element);
}

enum _TagClosingState {
  // Represents that the tag's close has not been parsed.
  notClosed,
  // Represents that the tag's close has been parsed as ">".
  closed,
  // Represents that the tag's close has been parsed as "/>", "?>", indicating
  // an empty element, as per https://www.w3.org/TR/xml/#sec-starttags.
  closedEmptyElement,
}

class _XmlAttribute {
  final String name;
  final String value;
  final SourceSpan sourceSpan;

  _XmlAttribute(this.name, this.value, this.sourceSpan);
}

class _XmlElement {
  final String name;
  final Map<String, _XmlAttribute> attributes;
  final List<_XmlElement> children;
  final SourceSpan? sourceSpan;

  _XmlElement(this.name, this.attributes, this.children, this.sourceSpan);
}
