// 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:glob/glob.dart';
import 'package:path/path.dart' as p;
import 'package:source_span/source_span.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 SourceSpan 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<Glob> 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<Glob> excludes;

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

  /// Returns whether this transformer might transform a file that's visible to
  /// the package's dependers.
  bool get canTransformPublicFiles {
    if (includes == null) return true;
    return includes.any((glob) {
      // Check whether the first path component of the glob is "lib", "bin", or
      // contains wildcards that may cause it to match "lib" or "bin".
      var first = p.posix.split(glob.toString()).first;
      if (first.contains('{') || first.contains('*') || first.contains('[') ||
          first.contains('?')) {
        return true;
      }

      return first == 'lib' || first == 'bin';
    });
  }

  /// Parses [identifier] as a [TransformerId] with [configuration].
  ///
  /// [identifierSpan] is the source span for [identifier].
  factory TransformerConfig.parse(String identifier, SourceSpan 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([new Glob(field, context: p.url, recursive: true)]);
      }

      if (field is! List) {
        throw new SourceSpanFormatException(
            '"$key" field must be a string or list.', fieldNode.span);
      }

      return new Set.from(field.nodes.map((node) {
        if (node.value is String) {
          return new Glob(node.value, context: p.url, recursive: true);
        }

        throw new SourceSpanFormatException(
            '"$key" field may contain only strings.', node.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 SourceSpanFormatException(
            '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) {
    if (excludes != null) {
      // If there are any excludes, it must not match any of them.
      for (var exclude in excludes) {
        if (exclude.matches(pathWithinPackage)) return false;
      }
    }

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