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

/// `usage` is a wrapper around Google Analytics for both command-line apps
/// and web apps.
///
/// In order to use this library as a web app, import the `analytics_html.dart`
/// library and instantiate the [AnalyticsHtml] class.
///
/// In order to use this library as a command-line app, import the
/// `analytics_io.dart` library and instantiate the [AnalyticsIO] class.
///
/// For both classes, you need to provide a Google Analytics tracking ID, the
/// application name, and the application version.
///
/// Your application should provide an opt-in option for the user. If they
/// opt-in, set the [optIn] field to `true`. This setting will persist across
/// sessions automatically.
///
/// For more information, please see the Google Analytics Measurement Protocol
/// [Policy](https://developers.google.com/analytics/devguides/collection/protocol/policy).
library usage;

import 'dart:async';

// Matches file:/, non-ws, /, non-ws, .dart
final RegExp _pathRegex = new RegExp(r'file:/\S+/(\S+\.dart)');

// Match multiple tabs or spaces.
final RegExp _tabOrSpaceRegex = new RegExp(r'[\t ]+');

/// An interface to a Google Analytics session.
///
/// [AnalyticsHtml] and [AnalyticsIO] are concrete implementations of this
/// interface. [AnalyticsMock] can be used for testing or for some variants of
/// an opt-in workflow.
///
/// The analytics information is sent on a best-effort basis. So, failures to
/// send the GA information will not result in errors from the asynchronous
/// `send` methods.
abstract class Analytics {
  /// Tracking ID / Property ID.
  String get trackingId;

  /// The application name.
  String get applicationName;

  /// The application version.
  String get applicationVersion;

  /// Is this the first time the tool has run?
  bool get firstRun;

  /// Whether the [Analytics] instance is configured in an opt-in or opt-out
  /// manner.
  AnalyticsOpt analyticsOpt = AnalyticsOpt.optOut;

  /// Will analytics data be sent.
  bool get enabled;

  /// Enable or disable sending of analytics data.
  set enabled(bool value);

  /// Anonymous client ID in UUID v4 format.
  ///
  /// The value is randomly-generated and should be reasonably stable for the
  /// computer sending analytics data.
  String get clientId;

  /// Sends a screen view hit to Google Analytics.
  ///
  /// [parameters] can be any analytics key/value pair. Useful
  /// for custom dimensions, etc.
  Future sendScreenView(String viewName, {Map<String, String> parameters});

  /// Sends an Event hit to Google Analytics. [label] specifies the event label.
  /// [value] specifies the event value. Values must be non-negative.
  ///
  /// [parameters] can be any analytics key/value pair. Useful
  /// for custom dimensions, etc.
  Future sendEvent(String category, String action,
      {String label, int value, Map<String, String> parameters});

  /// Sends a Social hit to Google Analytics.
  ///
  /// [network] specifies the social network, for example Facebook or Google
  /// Plus. [action] specifies the social interaction action. For example on
  /// Google Plus when a user clicks the +1 button, the social action is 'plus'.
  /// [target] specifies the target of a
  /// social interaction. This value is typically a URL but can be any text.
  Future sendSocial(String network, String action, String target);

  /// Sends a Timing hit to Google Analytics. [variableName] specifies the
  /// variable name of the timing. [time] specifies the user timing value (in
  /// milliseconds). [category] specifies the category of the timing. [label]
  /// specifies the label of the timing.
  Future sendTiming(String variableName, int time,
      {String category, String label});

  /// Start a timer. The time won't be calculated, and the analytics information
  /// sent, until the [AnalyticsTimer.finish] method is called.
  AnalyticsTimer startTimer(String variableName,
      {String category, String label});

  /// In order to avoid sending any personally identifying information, the
  /// [description] field must not contain the exception message. In addition,
  /// only the first 100 chars of the description will be sent.
  Future sendException(String description, {bool fatal});

  /// Gets a session variable value.
  dynamic getSessionValue(String param);

  /// Sets a session variable value. The value is persistent for the life of the
  /// [Analytics] instance. This variable will be sent in with every analytics
  /// hit. A list of valid variable names can be found here:
  /// https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters.
  void setSessionValue(String param, dynamic value);

  /// Fires events when the usage library sends any data over the network. This
  /// will not fire if analytics has been disabled or if the throttling
  /// algorithm has been engaged.
  ///
  /// This method is public to allow library clients to more easily test their
  /// analytics implementations.
  Stream<Map<String, dynamic>> get onSend;

  /// Wait for all of the outstanding analytics pings to complete. The returned
  /// `Future` will always complete without errors. You can pass in an optional
  /// `Duration` to specify to only wait for a certain amount of time.
  ///
  /// This method is particularly useful for command-line clients. Outstanding
  /// I/O requests will cause the VM to delay terminating the process.
  /// Generally, users won't want their CLI app to pause at the end of the
  /// process waiting for Google analytics requests to complete. This method
  /// allows CLI apps to delay for a short time waiting for GA requests to
  /// complete, and then do something like call `dart:io`'s `exit()` explicitly
  /// themselves (or the [close] method below).
  Future waitForLastPing({Duration timeout});

  /// Free any used resources.
  ///
  /// The [Analytics] instance should not be used after this call.
  void close();
}

enum AnalyticsOpt {
  /// Users must opt-in before any analytics data is sent.
  optIn,

  /// Users must opt-out for analytics data to not be sent.
  optOut
}

/// An object, returned by [Analytics.startTimer], that is used to measure an
/// asynchronous process.
class AnalyticsTimer {
  final Analytics analytics;
  final String variableName;
  final String category;
  final String label;

  int _startMillis;
  int _endMillis;

  AnalyticsTimer(this.analytics, this.variableName,
      {this.category, this.label}) {
    _startMillis = new DateTime.now().millisecondsSinceEpoch;
  }

  int get currentElapsedMillis {
    if (_endMillis == null) {
      return new DateTime.now().millisecondsSinceEpoch - _startMillis;
    } else {
      return _endMillis - _startMillis;
    }
  }

  /// Finish the timer, calculate the elapsed time, and send the information to
  /// analytics. Once this is called, any future invocations are no-ops.
  Future finish() {
    if (_endMillis != null) return new Future.value();

    _endMillis = new DateTime.now().millisecondsSinceEpoch;
    return analytics.sendTiming(variableName, currentElapsedMillis,
        category: category, label: label);
  }
}

/// A no-op implementation of the [Analytics] class. This can be used as a
/// stand-in for that will never ping the GA server, or as a mock in test code.
class AnalyticsMock implements Analytics {
  @override
  String get trackingId => 'UA-0';
  @override
  String get applicationName => 'mock-app';
  @override
  String get applicationVersion => '1.0.0';

  final bool logCalls;

  /// Events are never added to this controller for the mock implementation.
  final StreamController<Map<String, dynamic>> _sendController =
      new StreamController.broadcast();

  /// Create a new [AnalyticsMock]. If [logCalls] is true, all calls will be
  /// logged to stdout.
  AnalyticsMock([this.logCalls = false]);

  @override
  bool get firstRun => false;

  @override
  AnalyticsOpt analyticsOpt = AnalyticsOpt.optOut;

  @override
  bool enabled = true;

  @override
  String get clientId => '00000000-0000-4000-0000-000000000000';

  @override
  Future sendScreenView(String viewName, {Map<String, String> parameters}) {
    parameters ??= <String, String>{};
    parameters['viewName'] = viewName;
    return _log('screenView', parameters);
  }

  @override
  Future sendEvent(String category, String action,
      {String label, int value, Map<String, String> parameters}) {
    parameters ??= <String, String>{};
    return _log(
        'event',
        {'category': category, 'action': action, 'label': label, 'value': value}
          ..addAll(parameters));
  }

  @override
  Future sendSocial(String network, String action, String target) =>
      _log('social', {'network': network, 'action': action, 'target': target});

  @override
  Future sendTiming(String variableName, int time,
      {String category, String label}) {
    return _log('timing', {
      'variableName': variableName,
      'time': time,
      'category': category,
      'label': label
    });
  }

  @override
  AnalyticsTimer startTimer(String variableName,
      {String category, String label}) {
    return new AnalyticsTimer(this, variableName,
        category: category, label: label);
  }

  @override
  Future sendException(String description, {bool fatal}) =>
      _log('exception', {'description': description, 'fatal': fatal});

  @override
  dynamic getSessionValue(String param) => null;

  @override
  void setSessionValue(String param, dynamic value) {}

  @override
  Stream<Map<String, dynamic>> get onSend => _sendController.stream;

  @override
  Future waitForLastPing({Duration timeout}) => new Future.value();

  @override
  void close() {}

  Future _log(String hitType, Map m) {
    if (logCalls) {
      print('analytics: ${hitType} ${m}');
    }

    return new Future.value();
  }
}

/// Sanitize a stacktrace. This will shorten file paths in order to remove any
/// PII that may be contained in the full file path. For example, this will
/// shorten `file:///Users/foobar/tmp/error.dart` to `error.dart`.
///
/// If [shorten] is `true`, this method will also attempt to compress the text
/// of the stacktrace. GA has a 100 char limit on the text that can be sent for
/// an exception. This will try and make those first 100 chars contain
/// information useful to debugging the issue.
String sanitizeStacktrace(dynamic st, {bool shorten: true}) {
  String str = '${st}';

  Iterable<Match> iter = _pathRegex.allMatches(str);
  iter = iter.toList().reversed;

  for (Match match in iter) {
    String replacement = match.group(1);
    str =
        str.substring(0, match.start) + replacement + str.substring(match.end);
  }

  if (shorten) {
    // Shorten the stacktrace up a bit.
    str = str.replaceAll(_tabOrSpaceRegex, ' ');
  }

  return str;
}
