// 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.

@experimental
library build_runner.src.generate.performance_tracker;

import 'dart:async';

import 'package:build/build.dart';
import 'package:json_annotation/json_annotation.dart';
import 'package:meta/meta.dart';
import 'package:timing/timing.dart';

import 'phase.dart';

part 'performance_tracker.g.dart';

/// The [TimeSlice] of an entire build, including all its [actions].
@JsonSerializable()
class BuildPerformance extends TimeSlice {
  /// The [TimeSlice] of each phase ran in this build.
  final Iterable<BuildPhasePerformance> phases;

  /// The [TimeSlice] of running an individual [Builder] on an individual input.
  final Iterable<BuilderActionPerformance> actions;

  BuildPerformance(
      this.phases, this.actions, DateTime startTime, DateTime stopTime)
      : super(startTime, stopTime);

  factory BuildPerformance.fromJson(Map<String, dynamic> json) =>
      _$BuildPerformanceFromJson(json);

  @override
  Map<String, dynamic> toJson() => _$BuildPerformanceToJson(this);
}

/// The [TimeSlice] of a full [BuildPhase] within a larger build.
@JsonSerializable()
class BuildPhasePerformance extends TimeSlice {
  final List<String> builderKeys;

  BuildPhasePerformance(this.builderKeys, DateTime startTime, DateTime stopTime)
      : super(startTime, stopTime);

  factory BuildPhasePerformance.fromJson(Map<String, dynamic> json) =>
      _$BuildPhasePerformanceFromJson(json);

  @override
  Map<String, dynamic> toJson() => _$BuildPhasePerformanceToJson(this);
}

/// The [TimeSlice] of a [builderKey] running on [primaryInput] within a build.
@JsonSerializable()
class BuilderActionPerformance extends TimeSlice {
  final String builderKey;

  @JsonKey(fromJson: _assetIdFromJson, toJson: _assetIdToJson)
  final AssetId primaryInput;

  final Iterable<BuilderActionStagePerformance> stages;

  Duration get innerDuration => stages.fold(
      Duration.zero, (duration, stage) => duration + stage.innerDuration);

  BuilderActionPerformance(this.builderKey, this.primaryInput, this.stages,
      DateTime startTime, DateTime stopTime)
      : super(startTime, stopTime);

  factory BuilderActionPerformance.fromJson(Map<String, dynamic> json) =>
      _$BuilderActionPerformanceFromJson(json);

  @override
  Map<String, dynamic> toJson() => _$BuilderActionPerformanceToJson(this);
}

/// The [TimeSlice] of a particular task within a builder action.
///
/// This is some slice of overall [BuilderActionPerformance].
@JsonSerializable()
class BuilderActionStagePerformance extends TimeSliceGroup {
  final String label;

  BuilderActionStagePerformance(this.label, List<TimeSlice> slices)
      : super(slices);

  factory BuilderActionStagePerformance.fromJson(Map<String, dynamic> json) =>
      _$BuilderActionStagePerformanceFromJson(json);

  @override
  Map<String, dynamic> toJson() => _$BuilderActionStagePerformanceToJson(this);
}

/// Interface for tracking the overall performance of a build.
abstract class BuildPerformanceTracker
    implements TimeTracker, BuildPerformance {
  /// Tracks [runPhase] which performs [action] on all inputs in a phase, and
  /// return the outputs generated.
  Future<Iterable<AssetId>> trackBuildPhase(
      BuildPhase action, Future<Iterable<AssetId>> Function() runPhase);

  /// Returns a [BuilderActionTracker] for tracking [builderKey] on
  /// [primaryInput] and adds it to [actions].
  BuilderActionTracker addBuilderAction(
      AssetId primaryInput, String builderKey);

  factory BuildPerformanceTracker() => _BuildPerformanceTrackerImpl();

  /// A [BuildPerformanceTracker] with as little overhead as possible. Does no
  /// actual tracking and does not implement many fields/methods.
  factory BuildPerformanceTracker.noOp() =>
      _NoOpBuildPerformanceTracker.sharedInstance;
}

/// Real implementation of [BuildPerformanceTracker].
///
/// Use [BuildPerformanceTracker] factory to get an instance.
class _BuildPerformanceTrackerImpl extends SimpleAsyncTimeTracker
    implements BuildPerformanceTracker {
  @override
  Iterable<BuildPhaseTracker> get phases => _phases;
  final _phases = <BuildPhaseTracker>[];

  @override
  Iterable<BuilderActionTracker> get actions => _actions;
  final _actions = <BuilderActionTracker>[];

  /// Tracks [action] which is ran with [runPhase].
  ///
  /// This represents running a [Builder] on a group of sources.
  ///
  /// Returns all the outputs generated by the phase.
  @override
  Future<Iterable<AssetId>> trackBuildPhase(
      BuildPhase action, Future<Iterable<AssetId>> Function() runPhase) {
    assert(isTracking);
    var tracker = BuildPhaseTracker(action);
    _phases.add(tracker);
    return tracker.track(runPhase);
  }

  /// Returns a new [BuilderActionTracker] and adds it to [actions].
  ///
  /// The [BuilderActionTracker] will already be started, but you must stop it.
  @override
  BuilderActionTracker addBuilderAction(
      AssetId primaryInput, String builderKey) {
    assert(isTracking);
    var tracker = BuilderActionTracker(primaryInput, builderKey);
    _actions.add(tracker);
    return tracker;
  }

  @override
  Map<String, dynamic> toJson() => _$BuildPerformanceToJson(this);
}

/// No-op implementation of [BuildPerformanceTracker].
///
/// Read-only fields will throw, and tracking methods just directly invoke their
/// closures without tracking anything.
///
/// Use [BuildPerformanceTracker.noOp] to get an instance.
class _NoOpBuildPerformanceTracker extends NoOpTimeTracker
    implements BuildPerformanceTracker {
  static final _NoOpBuildPerformanceTracker sharedInstance =
      _NoOpBuildPerformanceTracker();

  @override
  Iterable<BuilderActionTracker> get actions => throw UnimplementedError();

  @override
  Iterable<BuildPhaseTracker> get phases => throw UnimplementedError();

  @override
  BuilderActionTracker addBuilderAction(
          AssetId primaryInput, String builderKey) =>
      BuilderActionTracker.noOp();

  @override
  Future<Iterable<AssetId>> trackBuildPhase(
          BuildPhase action, Future<Iterable<AssetId>> Function() runPhase) =>
      runPhase();

  @override
  Map<String, dynamic> toJson() => _$BuildPerformanceToJson(this);
}

/// Internal class that tracks the [TimeSlice] of an entire [BuildPhase].
///
/// Tracks total time it took to run on all inputs available to that action.
///
/// Use [track] to start actually tracking an operation.
///
/// This is only meaningful for non-lazy phases.
class BuildPhaseTracker extends SimpleAsyncTimeTracker
    implements BuildPhasePerformance {
  @override
  final List<String> builderKeys;

  BuildPhaseTracker(BuildPhase action)
      : builderKeys = action is InBuildPhase
            ? [action.builderLabel]
            : (action as PostBuildPhase)
                .builderActions
                .map((action) => action.builderLabel)
                .toList();

  @override
  Map<String, dynamic> toJson() => _$BuildPhasePerformanceToJson(this);
}

/// Interface for tracking the [TimeSlice] of an individual [Builder] on a given
/// primary input.
abstract class BuilderActionTracker
    implements TimeTracker, BuilderActionPerformance, StageTracker {
  /// Tracks the time of [runStage] and associates it with [label].
  ///
  /// You can specify [runStage] as [isExternal] (waiting for some external
  /// resource like network, process or file IO). In that case [runStage] will
  /// be tracked as single time slice from the beginning of the stage till
  /// completion of Future returned by [runStage].
  ///
  /// Otherwise all separate time slices of asynchronous execution will be
  /// tracked, but waiting for external resources will be a gap.
  @override
  T trackStage<T>(String label, T Function() runStage,
      {bool isExternal = false});

  factory BuilderActionTracker(AssetId primaryInput, String builderKey) =>
      _BuilderActionTrackerImpl(primaryInput, builderKey);

  /// A [BuilderActionTracker] with as little overhead as possible. Does no
  /// actual tracking and does not implement many fields/methods.
  factory BuilderActionTracker.noOp() =>
      _NoOpBuilderActionTracker._sharedInstance;
}

/// Real implementation of [BuilderActionTracker] which records timings.
///
/// Use the [BuilderActionTracker] factory to get an instance.
class _BuilderActionTrackerImpl extends SimpleAsyncTimeTracker
    implements BuilderActionTracker {
  @override
  final String builderKey;
  @override
  final AssetId primaryInput;

  @override
  final List<BuilderActionStageTracker> stages = [];

  @override
  Duration get innerDuration => stages.fold(
      Duration.zero, (duration, stage) => duration + stage.innerDuration);

  _BuilderActionTrackerImpl(this.primaryInput, this.builderKey);

  @override
  T trackStage<T>(String label, T Function() action,
      {bool isExternal = false}) {
    var tracker = isExternal
        ? BuilderActionStageSimpleTracker(label)
        : BuilderActionStageAsyncTracker(label);
    stages.add(tracker);
    return tracker.track(action);
  }

  @override
  Map<String, dynamic> toJson() => _$BuilderActionPerformanceToJson(this);
}

/// No-op instance of [BuilderActionTracker] which does nothing and throws an
/// unimplemented error for everything but [trackStage], which delegates directly to
/// the wrapped function.
///
/// Use the [BuilderActionTracker.noOp] factory to get an instance.
class _NoOpBuilderActionTracker extends NoOpTimeTracker
    implements BuilderActionTracker {
  static final _NoOpBuilderActionTracker _sharedInstance =
      _NoOpBuilderActionTracker();

  @override
  String get builderKey => throw UnimplementedError();

  @override
  Duration get duration => throw UnimplementedError();

  @override
  Iterable<BuilderActionStagePerformance> get stages =>
      throw UnimplementedError();

  @override
  Duration get innerDuration => throw UnimplementedError();

  @override
  AssetId get primaryInput => throw UnimplementedError();

  @override
  T trackStage<T>(String label, T Function() runStage,
          {bool isExternal = false}) =>
      runStage();

  @override
  Map<String, dynamic> toJson() => _$BuilderActionPerformanceToJson(this);
}

/// Tracks the [TimeSliceGroup] of an individual task.
///
/// These represent a slice of the [BuilderActionPerformance].
abstract class BuilderActionStageTracker
    implements BuilderActionStagePerformance {
  T track<T>(T Function() action);
}

class BuilderActionStageAsyncTracker extends AsyncTimeTracker
    implements BuilderActionStageTracker {
  @override
  final String label;

  BuilderActionStageAsyncTracker(this.label) : super(trackNested: false);

  @override
  Map<String, dynamic> toJson() => _$BuilderActionStagePerformanceToJson(this);
}

class BuilderActionStageSimpleTracker extends BuilderActionStagePerformance
    implements BuilderActionStageTracker {
  final _tracker = SimpleAsyncTimeTracker();

  BuilderActionStageSimpleTracker(String label) : super(label, []) {
    slices.add(_tracker);
  }

  @override
  T track<T>(T Function() action) => _tracker.track(action);
}

AssetId _assetIdFromJson(String json) => AssetId.parse(json);

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