import 'dart:collection';

import 'package:guru_utils/datetime/datetime_utils.dart';
import 'package:guru_utils/log/log.dart';

/// Created by Haoyi on 2023/1/24
abstract class Analytics {
  static final DoubleLinkedQueue<MapEntry<String, String>> latestEventRecords = DoubleLinkedQueue();
  static final Map<String, String> userProperties = {};

  Analytics() {
    AnalyticsUtils._analytics = this;
  }

  void recordEvents(String name, Map<String, dynamic> params) async {
    latestEventRecords.addFirst(MapEntry("$name [${DateTimeUtils.humanTime}]", params.toString()));
    if (latestEventRecords.length > 300) {
      latestEventRecords.removeLast();
    }
  }

  void recordProperty(String name, String value) async {
    userProperties[name] = value;
    Log.d("==> set property $name = $value");
  }

  Future<String> getAppInstanceId();

  void setScreen(String screenName);

  void logEvent(String eventName, Map<String, dynamic> parameters);

  void logEventEx(String eventName,
      {String? itemCategory,
      String? itemName,
      double? value,
      Map<String, dynamic> parameters = const {}});

  Future setUserProperty(String key, String value);

  void logException(dynamic exception, {StackTrace? stacktrace});

  void logFirebase(String msg);
}

class AnalyticsUtils {
  static Analytics? _analytics;
  static AnalyticsUtils instance = AnalyticsUtils._();

  AnalyticsUtils._();

  void setScreen(String screenName) {
    _analytics?.setScreen(screenName);
  }

  void logEvent(String eventName, Map<String, dynamic> parameters) {
    _analytics?.logEvent(eventName, parameters);
  }

  void logEventEx(String eventName,
      {String? itemCategory,
      String? itemName,
      double? value,
      Map<String, dynamic> parameters = const {}}) {
    _analytics?.logEventEx(eventName,
        itemCategory: itemCategory, itemName: itemName, parameters: parameters);
  }

  Future setUserProperty(String key, String value) async {
    return await _analytics?.setUserProperty(key, value);
  }

  void logException(dynamic exception, {StackTrace? stacktrace}) {
    _analytics?.logException(exception, stacktrace: stacktrace);
  }

  void logFirebase(String msg) {
    _analytics?.logFirebase(msg);
  }
}
