/// Created by Haoyi on 5/7/21

part of '../ads.dart';

mixin AdsAudit<T> on Ads {
  int latestShownAt = 0;
  int latestStartLoadAt = 0;
  int latestLoadedAt = 0;
  int latestHiddenAt = 0;
  String scene = "";
  int loadCount = 0;

  int get elapsedTimeInMillisSinceLoadedAds => DateTimeUtils.currentTimeInMillis() - latestLoadedAt;

  int get elapsedTimeInMillisSinceStartLoadAds =>
      DateTimeUtils.currentTimeInMillis() - latestStartLoadAt;

  void resetLatestLoadedAt() {
    latestLoadedAt = 0;
  }

  void resetAudit() {
    latestShownAt = 0;
    latestHiddenAt = 0;
    latestLoadedAt = 0;
    latestStartLoadAt = 0;
    scene = "";
  }
}

class AdsAuditObserver extends AdsLifecycleObserver {
  String adsName;

  final String tag;

  AdsAuditObserver(this.adsName, {this.tag = PropertyTags.ads});

  @override
  String get name => "$adsName-AuditObs";

  void _apply(AdsBundle adsBundle, void Function(AdsAudit) callback) {
    if (adsBundle.ads is AdsAudit) {
      callback(adsBundle.ads as AdsAudit);
    }
  }

  @override
  void onRequestShow(AdsBundle adsBundle) {
    Log.i("[$name] onRequestShow! ${adsBundle.arguments}", tag: tag);
    _apply(adsBundle, (adsAudit) {
      final adCause = adsBundle.getValue<AdCause>("cause", defValue: AdCause.internalError);
      if (adCause == AdCause.success) {
        adsAudit.scene = adsBundle.getString("scene");
        adsAudit.setProperty("latestScene", adsAudit.scene);
      }
    });
  }

  @override
  void onRequestLoad(AdsBundle adsBundle) {
    Log.i("[$name] onRequestLoad! ", tag: tag);
    _apply(adsBundle, (adsAudit) {
      final adCause = adsBundle.getValue<AdCause>("cause", defValue: AdCause.internalError);
      final now = DateTimeUtils.currentTimeInMillis();
      final humanDate = DateTime.fromMillisecondsSinceEpoch(now).toString();
      if (adCause == AdCause.success) {
        adsAudit.latestStartLoadAt = now;
        adsAudit.setProperty("latestStartLoadTime", humanDate);
        adsAudit.loadCount++;
        adsAudit.setProperty("winCount", adsAudit.loadCount.toString());
      } else {
        adsAudit.setProperty("latestLoadCause", "[$humanDate]:${adCause.toString()}");
      }
    });
  }

  @override
  void onRequestReset(AdsBundle adsBundle) {
    Log.i("[$name] onRequestReset! ", tag: tag);
    _apply(adsBundle, (adsAudit) async {
      adsAudit.resetAudit();
    });
  }

  @override
  void onAdLoaded(AdsBundle adsBundle) {
    Log.i("[$name] onAdLoaded! ", tag: tag);
    _apply(adsBundle, (adsAudit) {
      adsAudit.latestLoadedAt = DateTimeUtils.currentTimeInMillis();
      adsAudit.setProperty("latestLoadedTime",
          DateTime.fromMillisecondsSinceEpoch(adsAudit.latestLoadedAt).toString());
    });
  }

  @override
  void onAdLoadFailed(AdsBundle adsBundle) {
    Log.i("[$name] onAdLoadFailed! ", tag: tag);
    _apply(adsBundle, (adsAudit) {
      adsAudit.setProperty("latestLoadFailedTime", DateTime.now().toString());
    });
  }

  @override
  Future<void> onAdDisplayFailed(AdsBundle adsBundle) async {
    Log.i("[$name] onHidden! ", tag: tag);
    _apply(adsBundle, (adsAudit) {
      adsAudit.setProperty("latestDisplayFailedTime", DateTime.now().toString());
      adsAudit.setProperty("latestCreativeId", adsBundle.getString("ad_creative_id"));
      adsAudit.setProperty("latestNetworkName", adsBundle.getString("ad_network_name"));
    });
  }

  @override
  void onAdDisplayed(AdsBundle adsBundle) {
    Log.i("[$name] onAdDisplayed! ", tag: tag);
    _apply(adsBundle, (adsAudit) {
      adsAudit.setProperty("latestDisplayTime", DateTime.now().toString());
      adsAudit.setProperty("latestCreativeId", adsBundle.getString("ad_creative_id"));
      adsAudit.setProperty("latestNetworkName", adsBundle.getString("ad_network_name"));
    });
  }

  @override
  void onAdClicked(AdsBundle adsBundle) {}

  @override
  void onAdHidden(AdsBundle adsBundle) {
    Log.i("[$name] onHidden! ", tag: tag);

    _apply(adsBundle, (adsAudit) {
      final now = DateTime.now();
      adsAudit.latestHiddenAt = now.millisecondsSinceEpoch;
      adsAudit.setProperty("latestHiddenTime", now.toString());
      AdsManager.instance.latestFullscreenAdsHiddenTimestamps = now.millisecondsSinceEpoch;
    });
  }

  @override
  void onAdRewarded(AdsBundle adsBundle) {
    HookManager.instance.watchRewardAds();
  }
}
