// Copyright (c) 2017, 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/file_system/file_system.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/pubspec/pubspec_warning_code.dart';
import 'package:path/path.dart' as path;
import 'package:source_span/src/span.dart';
import 'package:yaml/yaml.dart';

class PubspecValidator {
  /// The name of the sub-field (under `flutter`) whose value is a list of
  /// assets available to Flutter apps at runtime.
  static const String ASSETS_FIELD = 'assets';

  /// The name of the field whose value is a map of dependencies.
  static const String DEPENDENCIES_FIELD = 'dependencies';

  /// The name of the field whose value is a map of development dependencies.
  static const String DEV_DEPENDENCIES_FIELD = 'dev_dependencies';

  /// The name of the field whose value is a specification of Flutter-specific
  /// configuration data.
  static const String FLUTTER_FIELD = 'flutter';

  /// The name of the field whose value is the name of the package.
  static const String NAME_FIELD = 'name';

  /// The resource provider used to access the file system.
  final ResourceProvider provider;

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

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

  /// Validate the given [contents].
  List<AnalysisError> validate(Map<dynamic, YamlNode> contents) {
    RecordingErrorListener recorder = RecordingErrorListener();
    ErrorReporter reporter = ErrorReporter(
      recorder,
      source,
      isNonNullableByDefault: false,
    );

    _validateDependencies(reporter, contents);
    _validateFlutter(reporter, contents);
    _validateName(reporter, contents);

    return recorder.errors;
  }

  /// Return `true` if an asset (file) exists at the given absolute, normalized
  /// [assetPath] or in a subdirectory of the parent of the file.
  bool _assetExistsAtPath(String assetPath) {
    // Check for asset directories.
    Folder assetDirectory = provider.getFolder(assetPath);
    if (assetDirectory.exists) {
      return true;
    }

    // Else, check for an asset file.
    File assetFile = provider.getFile(assetPath);
    if (assetFile.exists) {
      return true;
    }
    String fileName = assetFile.shortName;
    Folder assetFolder = assetFile.parent;
    if (!assetFolder.exists) {
      return false;
    }
    for (Resource child in assetFolder.getChildren()) {
      if (child is Folder) {
        File innerFile = child.getChildAssumingFile(fileName);
        if (innerFile.exists) {
          return true;
        }
      }
    }
    return false;
  }

  /// Return a map whose keys are the names of declared dependencies and whose
  /// values are the specifications of those dependencies. The map is extracted
  /// from the given [contents] using the given [key].
  Map<dynamic, YamlNode> _getDeclaredDependencies(
      ErrorReporter reporter, Map<dynamic, YamlNode> contents, String key) {
    YamlNode field = contents[key];
    if (field == null || (field is YamlScalar && field.value == null)) {
      return <String, YamlNode>{};
    } else if (field is YamlMap) {
      return field.nodes;
    }
    _reportErrorForNode(
        reporter, field, PubspecWarningCode.DEPENDENCIES_FIELD_NOT_MAP, [key]);
    return <String, YamlNode>{};
  }

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

  /// Validate the value of the required `name` field.
  void _validateDependencies(
      ErrorReporter reporter, Map<dynamic, YamlNode> contents) {
    Map<dynamic, YamlNode> declaredDependencies =
        _getDeclaredDependencies(reporter, contents, DEPENDENCIES_FIELD);
    Map<dynamic, YamlNode> declaredDevDependencies =
        _getDeclaredDependencies(reporter, contents, DEV_DEPENDENCIES_FIELD);

    for (YamlNode packageName in declaredDevDependencies.keys) {
      if (declaredDependencies.containsKey(packageName)) {
        _reportErrorForNode(reporter, packageName,
            PubspecWarningCode.UNNECESSARY_DEV_DEPENDENCY, [packageName.value]);
      }
    }
  }

  /// Validate the value of the optional `flutter` field.
  void _validateFlutter(
      ErrorReporter reporter, Map<dynamic, YamlNode> contents) {
    YamlNode flutterField = contents[FLUTTER_FIELD];
    if (flutterField is YamlMap) {
      YamlNode assetsField = flutterField.nodes[ASSETS_FIELD];
      if (assetsField is YamlList) {
        path.Context context = provider.pathContext;
        String packageRoot = context.dirname(source.fullName);
        for (YamlNode entryValue in assetsField.nodes) {
          if (entryValue is YamlScalar) {
            Object entry = entryValue.value;
            if (entry is String) {
              if (entry.startsWith('packages/')) {
                // TODO(brianwilkerson) Add validation of package references.
              } else {
                bool isDirectoryEntry = entry.endsWith("/");
                String normalizedEntry =
                    context.joinAll(path.posix.split(entry));
                String assetPath = context.join(packageRoot, normalizedEntry);
                if (!_assetExistsAtPath(assetPath)) {
                  ErrorCode errorCode = isDirectoryEntry
                      ? PubspecWarningCode.ASSET_DIRECTORY_DOES_NOT_EXIST
                      : PubspecWarningCode.ASSET_DOES_NOT_EXIST;
                  _reportErrorForNode(
                      reporter, entryValue, errorCode, [entryValue.value]);
                }
              }
            } else {
              _reportErrorForNode(
                  reporter, entryValue, PubspecWarningCode.ASSET_NOT_STRING);
            }
          } else {
            _reportErrorForNode(
                reporter, entryValue, PubspecWarningCode.ASSET_NOT_STRING);
          }
        }
      } else if (assetsField != null) {
        _reportErrorForNode(
            reporter, assetsField, PubspecWarningCode.ASSET_FIELD_NOT_LIST);
      }

      if (flutterField.length > 1) {
        // TODO(brianwilkerson) Should we report an error if `flutter` contains
        // keys other than `assets`?
      }
    } else if (flutterField != null) {
      if (flutterField.value == null) {
        // allow an empty `flutter:` section; explicitly fail on a non-empty,
        // non-map one
      } else {
        _reportErrorForNode(
            reporter, flutterField, PubspecWarningCode.FLUTTER_FIELD_NOT_MAP);
      }
    }
  }

  /// Validate the value of the required `name` field.
  void _validateName(ErrorReporter reporter, Map<dynamic, YamlNode> contents) {
    YamlNode nameField = contents[NAME_FIELD];
    if (nameField == null) {
      reporter.reportErrorForOffset(PubspecWarningCode.MISSING_NAME, 0, 0);
    } else if (nameField is! YamlScalar || nameField.value is! String) {
      _reportErrorForNode(
          reporter, nameField, PubspecWarningCode.NAME_NOT_STRING);
    }
  }
}
