// 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:convert' show JsonEncoder, jsonDecode;
import 'dart:io';

import 'package:meta/meta.dart';
import 'package:path/path.dart' as path;

import 'usage_impl.dart';

/// An interface to a Google Analytics session, suitable for use in command-line
/// applications.
///
/// [analyticsUrl] is an optional replacement for the default Google Analytics
/// URL (`https://www.google-analytics.com/collect`).
///
/// `trackingId`, `applicationName`, and `applicationVersion` values should be supplied.
/// `analyticsUrl` is optional, and lets user's substitute their own analytics URL for
/// the default.
///
/// `documentDirectory` is where the analytics settings are stored. It
/// defaults to the user home directory. For regular `dart:io` apps this doesn't need to
/// be supplied. For Flutter applications, you should pass in a value like
/// `PathProvider.getApplicationDocumentsDirectory()`.
///
/// [batchingDelay] is used to control batching behaviour. Events will be sent
/// batches of 20 after the duration is over from when the first message was
/// sent. The default is 0 milliseconds, meaning that messages will be sent when
/// control returns to the event loop.
///
/// Batched messages are sent in batches of up to 20 messages. They will be sent
/// to [analyticsBatchingUrl] defaulting to
/// `https://www.google-analytics.com/batch`.
class AnalyticsIO extends AnalyticsImpl {
  AnalyticsIO(
    String trackingId,
    String applicationName,
    String applicationVersion, {
    String? analyticsUrl,
    String? analyticsBatchingUrl,
    Directory? documentDirectory,
    HttpClient? client,
    Duration? batchingDelay,
  }) : super(
          trackingId,
          IOPersistentProperties(applicationName,
              documentDirPath: documentDirectory?.path),
          IOPostHandler(client: client),
          applicationName: applicationName,
          applicationVersion: applicationVersion,
          analyticsUrl: analyticsUrl,
          analyticsBatchingUrl: analyticsBatchingUrl,
          batchingDelay: batchingDelay,
        ) {
    final locale = getPlatformLocale();
    if (locale != null) {
      setSessionValue('ul', locale);
    }
  }
}

@visibleForTesting
String createUserAgent() {
  final locale = getPlatformLocale() ?? '';

  if (Platform.isAndroid) {
    return 'Mozilla/5.0 (Android; Mobile; ${locale})';
  } else if (Platform.isIOS) {
    return 'Mozilla/5.0 (iPhone; U; CPU iPhone OS like Mac OS X; ${locale})';
  } else if (Platform.isMacOS) {
    return 'Mozilla/5.0 (Macintosh; Intel Mac OS X; Macintosh; ${locale})';
  } else if (Platform.isWindows) {
    return 'Mozilla/5.0 (Windows; Windows; Windows; ${locale})';
  } else if (Platform.isLinux) {
    return 'Mozilla/5.0 (Linux; Linux; Linux; ${locale})';
  } else {
    // Dart/1.8.0 (macos; macos; macos; en_US)
    var os = Platform.operatingSystem;
    return 'Dart/${getDartVersion()} (${os}; ${os}; ${os}; ${locale})';
  }
}

String userHomeDir() {
  var envKey = Platform.operatingSystem == 'windows' ? 'APPDATA' : 'HOME';
  var value = Platform.environment[envKey];
  return value ?? '.';
}

String getDartVersion() {
  var ver = Platform.version;
  var index = ver.indexOf(' ');
  if (index != -1) ver = ver.substring(0, index);
  return ver;
}

class IOPostHandler extends PostHandler {
  final HttpClient _client;

  IOPostHandler({HttpClient? client})
      : _client = (client ?? HttpClient())..userAgent = createUserAgent();

  @override
  String encodeHit(Map<String, String> hit) {
    return postEncode(hit);
  }

  @override
  Future sendPost(String url, List<String> batch) async {
    var data = batch.join('\n');
    try {
      var req = await _client.postUrl(Uri.parse(url));
      req.write(data);
      var response = await req.close();
      await response.drain();
    } on Exception {
      // Catch errors that can happen during a request, but that we can't do
      // anything about, e.g. a missing internet connection.
    }
  }

  @override
  void close() {
    // Do a force close to ensure that lingering requests will not stall the
    // program.
    _client.close(force: true);
  }
}

JsonEncoder _jsonEncoder = JsonEncoder.withIndent('  ');

class IOPersistentProperties extends PersistentProperties {
  late final File _file;
  late Map _map;

  IOPersistentProperties(String name, {String? documentDirPath}) : super(name) {
    var fileName = '.${name.replaceAll(' ', '_')}';
    documentDirPath ??= userHomeDir();
    _file = File(path.join(documentDirPath, fileName));
    if (!_file.existsSync()) {
      _file.createSync();
    }
    syncSettings();
  }

  IOPersistentProperties.fromFile(File file) : super(path.basename(file.path)) {
    _file = file;
    if (!_file.existsSync()) {
      _file.createSync();
    }
    syncSettings();
  }

  @override
  dynamic operator [](String key) => _map[key];

  @override
  void operator []=(String key, dynamic value) {
    if (value == null && !_map.containsKey(key)) return;
    if (_map[key] == value) return;

    if (value == null) {
      _map.remove(key);
    } else {
      _map[key] = value;
    }

    try {
      _file.writeAsStringSync(_jsonEncoder.convert(_map) + '\n');
    } catch (_) {}
  }

  @override
  void syncSettings() {
    try {
      var contents = _file.readAsStringSync();
      if (contents.isEmpty) contents = '{}';
      _map = jsonDecode(contents);
    } catch (_) {
      _map = {};
    }
  }
}

/// Return the string for the platform's locale; return's `null` if the locale
/// can't be determined.
String? getPlatformLocale() {
  var locale = Platform.localeName;

  // Convert `en_US.UTF-8` to `en_US`.
  var index = locale.indexOf('.');
  if (index != -1) locale = locale.substring(0, index);

  // Convert `en_US` to `en-us`.
  locale = locale.replaceAll('_', '-').toLowerCase();

  return locale;
}
