// 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:html/dom.dart';
import 'package:html/parser.dart' show parseFragment;
import 'package:source_span/source_span.dart';

import 'manifest_values.dart';
import 'manifest_warning_code.dart';

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 contents, bool checkManifest) {
    RecordingErrorListener recorder = new RecordingErrorListener();
    ErrorReporter reporter = new ErrorReporter(recorder, source);

    if (checkManifest) {
      var document =
          parseFragment(contents, container: MANIFEST_TAG, generateSpans: true);
      var manifest = document.children.firstWhere(
          (element) => element.localName == MANIFEST_TAG,
          orElse: () => null);
      var features = manifest?.getElementsByTagName(USES_FEATURE_TAG) ?? [];
      var permissions =
          manifest?.getElementsByTagName(USES_PERMISSION_TAG) ?? [];
      var activities = _findActivityElements(manifest);

      _validateFeatures(features, reporter);
      _validatePermissions(permissions, features, reporter);
      _validateActivities(activities, reporter);
    }
    return recorder.errors;
  }

  /*
   * Validate the `uses-feature` tags.
   */
  _validateFeatures(List<Element> features, ErrorReporter reporter) {
    var unsupported = features
        .where((element) => UNSUPPORTED_HARDWARE_FEATURES
            .contains(element.attributes[ANDROID_NAME]))
        .toList();
    unsupported.forEach((element) {
      if (!element.attributes.containsKey(ANDROID_REQUIRED)) {
        _reportErrorForNode(reporter, element, ANDROID_NAME,
            ManifestWarningCode.UNSUPPORTED_CHROME_OS_HARDWARE);
      } else if (element.attributes[ANDROID_REQUIRED] == true) {
        _reportErrorForNode(reporter, element, ANDROID_NAME,
            ManifestWarningCode.UNSUPPORTED_CHROME_OS_HARDWARE);
      }
    });
  }

  /*
   * Validate the `uses-permission` tags.
   */
  _validatePermissions(List<Element> permissions, List<Element> features,
      ErrorReporter reporter) {
    permissions.forEach((permission) {
      if (permission.attributes[ANDROID_NAME] == 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]);
        if (featureName != null) {
          _reportErrorForNode(
              reporter,
              permission,
              ANDROID_NAME,
              ManifestWarningCode.PERMISSION_IMPLIES_UNSUPPORTED_HARDWARE,
              [featureName]);
        }
      }
    });
  }

  /*
   * Validate the 'activity' tags.
   */
  _validateActivities(List<Element> activites, ErrorReporter reporter) {
    activites.forEach((activity) {
      var attributes = activity.attributes;
      if (attributes.containsKey(ATTRIBUTE_SCREEN_ORIENTATION)) {
        var value = attributes[ATTRIBUTE_SCREEN_ORIENTATION];
        if (UNSUPPORTED_ORIENTATIONS
            .contains(attributes[ATTRIBUTE_SCREEN_ORIENTATION])) {
          _reportErrorForNode(reporter, activity, ATTRIBUTE_SCREEN_ORIENTATION,
              ManifestWarningCode.SETTING_ORIENTATION_ON_ACTIVITY);
        }
      }
      if (attributes.containsKey(ATTRIBUTE_RESIZEABLE_ACTIVITY)) {
        if (attributes[ATTRIBUTE_RESIZEABLE_ACTIVITY] == 'false') {
          _reportErrorForNode(reporter, activity, ATTRIBUTE_RESIZEABLE_ACTIVITY,
              ManifestWarningCode.NON_RESIZABLE_ACTIVITY);
        }
      }
    });
  }

  List<Element> _findActivityElements(Element manifest) {
    var applications = manifest?.getElementsByTagName(APPLICATION_TAG);
    var applicationElement = (applications != null && applications.isNotEmpty)
        ? applications.first
        : null;
    var activities =
        applicationElement?.getElementsByTagName(ACTIVITY_TAG) ?? [];
    return activities;
  }

  bool _hasFeatureCamera(List<Element> features) =>
      features.any((f) => f.localName == HARDWARE_FEATURE_CAMERA);

  bool _hasFeatureCameraAutoFocus(List<Element> features) =>
      features.any((f) => f.localName == HARDWARE_FEATURE_CAMERA_AUTOFOCUS);

  /**
   * Report an error for the given node.
   */
  void _reportErrorForNode(
      ErrorReporter reporter, Node node, dynamic key, ErrorCode errorCode,
      [List<Object> arguments]) {
    FileSpan span = node.attributeValueSpans[key];
    reporter.reportErrorForOffset(
        errorCode, span.start.offset, span.length, arguments);
  }
}
