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

import 'dart:async';
import 'dart:math' as math;

import '../usage.dart';
import 'uuid.dart';

final int _MAX_EXCEPTION_LENGTH = 100;

String postEncode(Map<String, dynamic> map) {
  // &foo=bar
  return map.keys.map((key) {
    String value = '${map[key]}';
    return "${key}=${Uri.encodeComponent(value)}";
  }).join('&');
}

/**
 * A throttling algorithim. This models the throttling after a bucket with
 * water dripping into it at the rate of 1 drop per second. If the bucket has
 * water when an operation is requested, 1 drop of water is removed and the
 * operation is performed. If not the operation is skipped. This algorithim
 * lets operations be peformed in bursts without throttling, but holds the
 * overall average rate of operations to 1 per second.
 */
class ThrottlingBucket {
  final int startingCount;
  int drops;
  int _lastReplenish;

  ThrottlingBucket(this.startingCount) {
    drops = startingCount;
    _lastReplenish = new DateTime.now().millisecondsSinceEpoch;
  }

  bool removeDrop() {
    _checkReplenish();

    if (drops <= 0) {
      return false;
    } else {
      drops--;
      return true;
    }
  }

  void _checkReplenish() {
    int now = new DateTime.now().millisecondsSinceEpoch;

    if (_lastReplenish + 1000 >= now) {
      int inc = (now - _lastReplenish) ~/ 1000;
      drops = math.min(drops + inc, startingCount);
      _lastReplenish += (1000 * inc);
    }
  }
}

class AnalyticsImpl implements Analytics {
  static const String _defaultAnalyticsUrl = 'https://www.google-analytics.com/collect';

  /**
   * Tracking ID / Property ID.
   */
  final String trackingId;

  final PersistentProperties properties;
  final PostHandler postHandler;

  final ThrottlingBucket _bucket = new ThrottlingBucket(20);
  final Map<String, dynamic> _variableMap = {};

  final List<Future> _futures = [];

  AnalyticsOpt analyticsOpt = AnalyticsOpt.optOut;

  String _url;

  StreamController<Map<String, dynamic>> _sendController = new StreamController.broadcast(sync: true);

  AnalyticsImpl(
    this.trackingId,
    this.properties,
    this.postHandler, {
    String applicationName,
    String applicationVersion,
    String analyticsUrl
  }) {
    assert(trackingId != null);

    if (applicationName != null) setSessionValue('an', applicationName);
    if (applicationVersion != null) setSessionValue('av', applicationVersion);

    _url = analyticsUrl ?? _defaultAnalyticsUrl;
  }

  bool _firstRun;

  bool get firstRun {
    if (_firstRun == null) {
      _firstRun = properties['firstRun'] == null;

      if (properties['firstRun'] != false) {
        properties['firstRun'] = false;
      }
    }

    return _firstRun;
  }

  /**
   * Will analytics data be sent?
   */
  bool get enabled {
    bool optIn = analyticsOpt == AnalyticsOpt.optIn;
    return optIn ? properties['enabled'] == true : properties['enabled'] != false;
  }

  /**
   * Enable or disable sending of analytics data.
   */
  set enabled(bool value) {
    properties['enabled'] = value;
  }

  Future sendScreenView(String viewName) {
    Map<String, dynamic> args = {'cd': viewName};
    return _sendPayload('screenview', args);
  }

  Future sendEvent(String category, String action, {String label, int value}) {
    Map<String, dynamic> args = {'ec': category, 'ea': action};
    if (label != null) args['el'] = label;
    if (value != null) args['ev'] = value;
    return _sendPayload('event', args);
  }

  Future sendSocial(String network, String action, String target) {
    Map<String, dynamic> args = {'sn': network, 'sa': action, 'st': target};
    return _sendPayload('social', args);
  }

  Future sendTiming(String variableName, int time, {String category, String label}) {
    Map<String, dynamic> args = {'utv': variableName, 'utt': time};
    if (label != null) args['utl'] = label;
    if (category != null) args['utc'] = category;
    return _sendPayload('timing', args);
  }

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

  Future sendException(String description, {bool fatal}) {
    // In order to ensure that the client of this API is not sending any PII
    // data, we strip out any stack trace that may reference a path on the
    // user's drive (file:/...).
    if (description.contains('file:/')) {
      description = description.substring(0, description.indexOf('file:/'));
    }

    if (description != null && description.length > _MAX_EXCEPTION_LENGTH) {
      description = description.substring(0, _MAX_EXCEPTION_LENGTH);
    }

    Map<String, dynamic> args = {'exd': description};
    if (fatal != null && fatal) args['exf'] = '1';
    return _sendPayload('exception', args);
  }

  dynamic getSessionValue(String param) => _variableMap[param];

  void setSessionValue(String param, dynamic value) {
    if (value == null) {
      _variableMap.remove(param);
    } else {
      _variableMap[param] = value;
    }
  }

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

  Future waitForLastPing({Duration timeout}) {
    Future f = Future.wait(_futures).catchError((e) => null);

    if (timeout != null) {
      f = f.timeout(timeout, onTimeout: () => null);
    }

    return f;
  }

  /**
   * Anonymous Client ID. The value of this field should be a random UUID v4.
   */
  String get _clientId => properties['clientId'];

  void _initClientId() {
    if (_clientId == null) {
      properties['clientId'] = new Uuid().generateV4();
    }
  }

  /**
   * Send raw data to analytics. Callers should generally use one of the typed
   * methods (`sendScreenView`, `sendEvent`, ...).
   *
   * Valid values for [hitType] are: 'pageview', 'screenview', 'event',
   * 'transaction', 'item', 'social', 'exception', and 'timing'.
   */
  Future sendRaw(String hitType, Map<String, dynamic> args) {
    return _sendPayload(hitType, args);
  }

  /**
   * Valid values for [hitType] are: 'pageview', 'screenview', 'event',
   * 'transaction', 'item', 'social', 'exception', and 'timing'.
   */
  Future _sendPayload(String hitType, Map<String, dynamic> args) {
    if (!enabled) return new Future.value();

    if (_bucket.removeDrop()) {
      _initClientId();

      _variableMap.forEach((key, value) {
        args[key] = value;
      });

      args['v'] = '1'; // protocol version
      args['tid'] = trackingId;
      args['cid'] = _clientId;
      args['t'] = hitType;

      _sendController.add(args);

      return _recordFuture(postHandler.sendPost(_url, args));
    } else {
      return new Future.value();
    }
  }

  Future _recordFuture(Future f) {
    _futures.add(f);
    return f.whenComplete(() => _futures.remove(f));
  }
}

/**
 * A persistent key/value store. An [AnalyticsImpl] instance expects to have one
 * of these injected into it. There are default implementations for `dart:io`
 * and `dart:html` clients.
 *
 * The [name] paramater is used to uniquely store these properties on disk /
 * persistent storage.
 */
abstract class PersistentProperties {
  final String name;

  PersistentProperties(this.name);

  dynamic operator[](String key);
  void operator[]=(String key, dynamic value);
}

/**
 * A utility class to perform HTTP POSTs. An [AnalyticsImpl] instance expects to
 * have one of these injected into it. There are default implementations for
 * `dart:io` and `dart:html` clients.
 *
 * The POST information should be sent on a best-effort basis. The `Future` from
 * [sendPost] should complete when the operation is finished, but failures to
 * send the information should be silent.
 */
abstract class PostHandler {
  Future sendPost(String url, Map<String, dynamic> parameters);
}
