// Copyright (c) 2016, 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:build/build.dart';
import 'package:build_config/build_config.dart';
import 'package:collection/collection.dart';
import 'package:meta/meta.dart';

import 'input_matcher.dart';

/// A "phase" in the build graph, which represents running a one or more
/// builders on a set of sources.
abstract class BuildPhase {
  /// Whether to run lazily when an output is read.
  ///
  /// An optional build action will only run if one of its outputs is read by
  /// a later [Builder], or is used as a primary input to a later [Builder].
  ///
  /// If no build actions read the output of an optional action, then it will
  /// never run.
  bool get isOptional;

  /// Whether generated assets should be placed in the build cache.
  ///
  /// When this is `false` the Builder may not run on any package other than
  /// the root.
  bool get hideOutput;

  /// The identity of this action in terms of a build graph. If the identity of
  /// any action changes the build will be invalidated.
  ///
  /// This should take into account everything except for the builderOptions,
  /// which are tracked separately via a `BuilderOptionsNode` which supports
  /// more fine grained invalidation.
  int get identity;
}

/// An "action" in the build graph which represents running a single builder
/// on a set of sources.
abstract class BuildAction {
  /// Either a [Builder] or a [PostProcessBuilder].
  dynamic get builder;
  String get builderLabel;
  BuilderOptions get builderOptions;
  InputMatcher get generateFor;
  String get package;
  InputMatcher get targetSources;
}

/// A [BuildPhase] that uses a single [Builder] to generate files.
class InBuildPhase extends BuildPhase implements BuildAction {
  @override
  final Builder builder;
  @override
  final String builderLabel;
  @override
  final BuilderOptions builderOptions;
  @override
  final InputMatcher generateFor;
  @override
  final String package;
  @override
  final InputMatcher targetSources;

  @override
  final bool isOptional;
  @override
  final bool hideOutput;

  InBuildPhase._(this.package, this.builder, this.builderOptions,
      {@required this.targetSources,
      @required this.generateFor,
      @required this.builderLabel,
      bool isOptional,
      bool hideOutput})
      : isOptional = isOptional ?? false,
        hideOutput = hideOutput ?? false;

  /// Creates an [BuildPhase] for a normal [Builder].
  ///
  /// The build target is defined by [package] as well as [targetSources]. By
  /// default all sources in the target are used as primary inputs to the
  /// builder, but it can be further filtered with [generateFor].
  ///
  /// [isOptional] specifies that a Builder may not be run unless some other
  /// Builder in a later phase attempts to read one of the potential outputs.
  ///
  /// [hideOutput] specifies that the generated asses should be placed in the
  /// build cache rather than the source tree.
  factory InBuildPhase(
    Builder builder,
    String package, {
    String builderKey,
    InputSet targetSources,
    InputSet generateFor,
    BuilderOptions builderOptions,
    bool isOptional,
    bool hideOutput,
  }) {
    var targetSourceMatcher = InputMatcher(targetSources ?? const InputSet());
    var generateForMatcher = InputMatcher(generateFor ?? const InputSet());
    builderOptions ??= const BuilderOptions({});
    return InBuildPhase._(package, builder, builderOptions,
        targetSources: targetSourceMatcher,
        generateFor: generateForMatcher,
        builderLabel: builderKey == null || builderKey.isEmpty
            ? _builderLabel(builder)
            : _simpleBuilderKey(builderKey),
        isOptional: isOptional,
        hideOutput: hideOutput);
  }

  @override
  String toString() {
    final settings = <String>[];
    if (isOptional) settings.add('optional');
    if (hideOutput) settings.add('hidden');
    var result = '$builderLabel on $targetSources in $package';
    if (settings.isNotEmpty) result += ' $settings';
    return result;
  }

  @override
  int get identity => _deepEquals.hash([
        builderLabel,
        builder.buildExtensions,
        package,
        targetSources,
        generateFor,
        isOptional,
        hideOutput
      ]);
}

/// A [BuildPhase] that can run multiple [PostBuildAction]s to
/// generate files.
///
/// There should only be one of these per build, and it should be the final
/// phase.
class PostBuildPhase extends BuildPhase {
  final List<PostBuildAction> builderActions;

  @override
  bool get hideOutput => true;
  @override
  bool get isOptional => false;

  PostBuildPhase(this.builderActions);

  @override
  String toString() =>
      '${builderActions.map((a) => a.builderLabel).join(', ')}';

  @override
  int get identity =>
      _deepEquals.hash(builderActions.map<dynamic>((b) => b.identity).toList()
        ..addAll([
          isOptional,
          hideOutput,
        ]));
}

/// Part of a larger [PostBuildPhase], applies a single
/// [PostProcessBuilder] to a single [package] with some additional options.
class PostBuildAction implements BuildAction {
  @override
  final PostProcessBuilder builder;
  @override
  final String builderLabel;
  @override
  final BuilderOptions builderOptions;
  @override
  final InputMatcher generateFor;
  @override
  final String package;
  @override
  final InputMatcher targetSources;

  PostBuildAction(this.builder, this.package,
      {String builderKey,
      @required BuilderOptions builderOptions,
      @required InputSet targetSources,
      @required InputSet generateFor})
      : builderLabel = builderKey == null || builderKey.isEmpty
            ? _builderLabel(builder)
            : _simpleBuilderKey(builderKey),
        builderOptions = builderOptions ?? const BuilderOptions({}),
        targetSources = InputMatcher(targetSources ?? const InputSet()),
        generateFor = InputMatcher(generateFor ?? const InputSet());

  int get identity => _deepEquals.hash([
        builderLabel,
        builder.inputExtensions.toList(),
        generateFor,
        package,
        targetSources,
      ]);
}

/// If we have no key find a human friendly name for the Builder.
String _builderLabel(Object builder) {
  var label = '$builder';
  if (label.startsWith('Instance of \'')) {
    label = label.substring(13, label.length - 1);
  }
  return label;
}

/// Change "angular|angular" to "angular".
String _simpleBuilderKey(String builderKey) {
  if (!builderKey.contains('|')) return builderKey;
  var parts = builderKey.split('|');
  if (parts[0] == parts[1]) return parts[0];
  return builderKey;
}

final _deepEquals = const DeepCollectionEquality();
