// Copyright (c) 2020, 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:convert';
import 'dart:io';

import 'package:meta/meta.dart';
import 'package:path/path.dart' as path;
import 'package:telemetry/telemetry.dart' as telemetry show isRunningOnBot;
import 'package:usage/src/usage_impl.dart';
import 'package:usage/src/usage_impl_io.dart';
import 'package:usage/usage_io.dart';

const String analyticsNoticeOnFirstRunMessage = '''
  ╔════════════════════════════════════════════════════════════════════════════╗
  ║ The Dart tool uses Google Analytics to report feature usage statistics     ║
  ║ and to send basic crash reports. This data is used to help improve the     ║
  ║ Dart platform and tools over time.                                         ║
  ║                                                                            ║
  ║ To disable reporting of analytics, run:                                    ║
  ║                                                                            ║
  ║   dart --disable-analytics                                                 ║
  ║                                                                            ║
  ╚════════════════════════════════════════════════════════════════════════════╝
''';
const String analyticsDisabledNoticeMessage = '''
  ╔════════════════════════════════════════════════════════════════════════════╗
  ║ Analytics reporting disabled. In order to enable it, run:                  ║
  ║                                                                            ║
  ║   dart --enable-analytics                                                  ║
  ║                                                                            ║
  ╚════════════════════════════════════════════════════════════════════════════╝
''';
const String _appName = 'dartdev';
const String _dartDirectoryName = '.dart';
const String _settingsFileName = 'dartdev.json';
const String _trackingId = 'UA-26406144-37';
const String _readmeFileName = 'README.txt';
const String _readmeFileContents = '''
This directory contains user-level settings for the Dart programming language
(https://dart.dev).
''';

const String eventCategory = 'dartdev';
const String exitCodeParam = 'exitCode';

/// Disabled [Analytics], exposed for testing only
@visibleForTesting
Analytics get disabledAnalytics => DisabledAnalytics(_trackingId, _appName);

/// Create and return an [Analytics] instance.
Analytics createAnalyticsInstance(bool disableAnalytics) {
  if (Platform.environment['_DARTDEV_LOG_ANALYTICS'] != null) {
    // Used for testing what analytics messages are sent.
    return _LoggingAnalytics();
  }

  if (disableAnalytics) {
    // Dartdev tests pass a hidden 'no-analytics' flag which is
    // handled here.
    //
    // Also, stdout.hasTerminal is checked; if there is no terminal we infer
    // that a machine is running dartdev so we return that analytics shouldn't
    // be set enabled.
    return DisabledAnalytics(_trackingId, _appName);
  }

  final settingsDir = getDartStorageDirectory();
  if (settingsDir == null) {
    // Some systems don't support user home directories; for those, fail
    // gracefully by returning a disabled analytics object.
    return DisabledAnalytics(_trackingId, _appName);
  }

  if (!settingsDir.existsSync()) {
    try {
      settingsDir.createSync();
    } catch (e) {
      // If we can't create the directory for the analytics settings, fail
      // gracefully by returning a disabled analytics object.
      return DisabledAnalytics(_trackingId, _appName);
    }
  }

  final readmeFile =
      File('${settingsDir.absolute.path}${path.separator}$_readmeFileName');
  if (!readmeFile.existsSync()) {
    readmeFile.createSync();
    readmeFile.writeAsStringSync(_readmeFileContents);
  }

  final settingsFile = File(path.join(settingsDir.path, _settingsFileName));
  return DartdevAnalytics(_trackingId, settingsFile, _appName);
}

/// The directory used to store the analytics settings file.
///
/// Typically, the directory is `~/.dart/` (and the settings file is
/// `dartdev.json`).
///
/// This can return null under some conditions, including when the user's home
/// directory does not exist.
Directory getDartStorageDirectory() {
  var homeDir = Directory(userHomeDir());
  if (!homeDir.existsSync()) {
    return null;
  }
  return Directory(path.join(homeDir.path, _dartDirectoryName));
}

/// The method used by dartdev to determine if this machine is a bot such as a
/// CI machine.
bool isBot() => telemetry.isRunningOnBot();

class DartdevAnalytics extends AnalyticsImpl {
  DartdevAnalytics(String trackingId, File settingsFile, String appName)
      : super(
          trackingId,
          IOPersistentProperties.fromFile(settingsFile),
          IOPostHandler(),
          applicationName: appName,
          applicationVersion: getDartVersion(),
          batchingDelay: Duration(),
        );

  @override
  bool get enabled {
    // Don't enable if the user hasn't been shown the disclosure or if this
    // machine is bot.
    if (!disclosureShownOnTerminal || isBot()) {
      return false;
    }

    // If there's no explicit setting (enabled or disabled) then we don't send.
    return (properties['enabled'] as bool) ?? false;
  }

  bool get disclosureShownOnTerminal =>
      (properties['disclosureShown'] as bool) ?? false;

  set disclosureShownOnTerminal(bool value) {
    properties['disclosureShown'] = value;
  }
}

@visibleForTesting
class DisabledAnalytics extends AnalyticsMock {
  @override
  final String trackingId;
  @override
  final String applicationName;

  DisabledAnalytics(this.trackingId, this.applicationName);

  @override
  bool get enabled => false;

  @override
  bool get firstRun => false;
}

class _LoggingAnalytics extends AnalyticsMock {
  _LoggingAnalytics() {
    onSend.listen((event) {
      stderr.writeln('[analytics]${json.encode(event)}');
    });
  }

  @override
  bool get firstRun => false;

  @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
    });
  }

  Future<void> _log(String hitType, Map message) async {
    final encoded = json.encode({'hitType': hitType, 'message': message});
    stderr.writeln('[analytics]: $encoded');
  }
}
