// Copyright (c) 2013, 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.

library pub.barback.transformer_config;

import 'package:source_maps/source_maps.dart';
import 'package:yaml/yaml.dart';

import 'transformer_id.dart';

/// The configuration for a transformer.
///
/// This corresponds to the transformers listed in a pubspec, which have both an
/// [id] indicating the location of the transformer and configuration specific
/// to that use of the transformer.
class TransformerConfig {
  /// The [id] of the transformer [this] is configuring.
  final TransformerId id;

  /// The configuration to pass to the transformer.
  ///
  /// Any pub-specific configuration (i.e. keys starting with "$") will have
  /// been stripped out of this and handled separately. This will be an empty
  /// map if no configuration was provided.
  final Map configuration;

  /// The source span from which this configuration was parsed.
  final Span span;

  /// The primary input inclusions.
  ///
  /// Each inclusion is an asset path. If this set is non-empty, then *only*
  /// matching assets are allowed as a primary input by this transformer. If
  /// `null`, all assets are included.
  ///
  /// This is processed before [excludes]. If a transformer has both includes
  /// and excludes, then the set of included assets is determined and assets
  /// are excluded from that resulting set.
  final Set<String> includes;

  /// The primary input exclusions.
  ///
  /// Any asset whose pach is in this is not allowed as a primary input by
  /// this transformer.
  ///
  /// This is processed after [includes]. If a transformer has both includes
  /// and excludes, then the set of included assets is determined and assets
  /// are excluded from that resulting set.
  final Set<String> excludes;

  /// Returns whether this config excludes certain asset ids from being
  /// processed.
  bool get hasExclusions => includes != null || excludes != null;

  /// Parses [identifier] as a [TransformerId] with [configuration].
  ///
  /// [identifierSpan] is the source span for [identifier].
  factory TransformerConfig.parse(String identifier, Span identifierSpan,
        YamlMap configuration) =>
      new TransformerConfig(new TransformerId.parse(identifier, identifierSpan),
          configuration);

  factory TransformerConfig(TransformerId id, YamlMap configurationNode) {
    parseField(key) {
      if (!configurationNode.containsKey(key)) return null;
      var fieldNode = configurationNode.nodes[key];
      var field = fieldNode.value;

      if (field is String) return new Set.from([field]);

      if (field is List) {
        for (var node in field.nodes) {
          if (node.value is String) continue;
          throw new SpanFormatException(
              '"$key" field may contain only strings.', node.span);
        }

        return new Set.from(field);
      } else {
        throw new SpanFormatException(
            '"$key" field must be a string or list.', fieldNode.span);
      }
    }

    var includes = null;
    var excludes = null;

    var configuration;
    var span;
    if (configurationNode == null) {
      configuration = {};
      span = id.span;
    } else {
      // Don't write to the immutable YAML map.
      configuration = new Map.from(configurationNode);
      span = configurationNode.span;

      // Pull out the exclusions/inclusions.
      includes = parseField("\$include");
      configuration.remove("\$include");
      excludes = parseField("\$exclude");
      configuration.remove("\$exclude");

      // All other keys starting with "$" are unexpected.
      for (var key in configuration.keys) {
        if (key is! String || !key.startsWith(r'$')) continue;
        throw new SpanFormatException(
            'Unknown reserved field.', configurationNode.nodes[key].span);
      }
    }

    return new TransformerConfig._(id, configuration, span, includes, excludes);
  }

  TransformerConfig._(
      this.id, this.configuration, this.span, this.includes, this.excludes);

  String toString() => id.toString();

  /// Returns whether the include/exclude rules allow the transformer to run on
  /// [pathWithinPackage].
  ///
  /// [pathWithinPackage] must be a URL-style path relative to the containing
  /// package's root directory.
  bool canTransform(String pathWithinPackage) {
    // TODO(rnystrom): Support globs in addition to paths. See #17093.
    if (excludes != null) {
      // If there are any excludes, it must not match any of them.
      if (excludes.contains(pathWithinPackage)) return false;
    }

    // If there are any includes, it must match one of them.
    return includes == null || includes.contains(pathWithinPackage);
  }
}
