import 'dart:async';

import 'package:flutter/cupertino.dart';
import 'package:guru_utils/ads/ads.dart';
import 'package:guru_utils/ads/data/ads_model.dart';
import 'package:guru_utils/controller/lifecycle_controller.dart';
import 'package:guru_utils/extensions/extensions.dart';
import 'package:guru_utils/log/log.dart';
import 'package:guru_utils/timer/timer_scheduler.dart';

import 'aware/controller_aware.dart';

/// Created by Haoyi on 2022/3/2

class AdsCompleter {
  final AdType adType;
  final Completer<AdsResult> completer;
  final DateTime at;

  AdsCompleter(this.adType)
      : completer = Completer.sync(),
        at = DateTime.now();

  void error(AdCause adCause) {
    Log.d("AdsCompleter error! $adCause", tag: "Ads");
    completer.complete(AdsResult.build(adType, adCause));
  }

  void success() {
    Log.d("AdsCompleter success!", tag: "Ads");
    completer.complete(AdsResult.success(adType));
  }

  void close() {
    Log.d("AdsCompleter close with ignore!", tag: "Ads");
    completer.safeComplete(AdsResult.build(adType, AdCause.ignore));
  }

  bool get isCompleted => completer.isCompleted;

  Future<AdsResult> waiting() {
    return completer.future;
  }
}

abstract class AdsController extends LifecycleController {
  AdsCompleter? adsCompleter;
  ActiveTimer? _autoCompleteFrozenAdsTimer;

  @override
  @mustCallSuper
  void onInit() {
    super.onInit();
    if (this is BannerAware) {
      (this as BannerAware).initBanner();
    } else if (this is SharedBannerAware) {
      (this as SharedBannerAware).initBanner();
    }

    if (this is InterstitialAware) {
      (this as InterstitialAware).bindInterstitialAd();
    }

    if (this is RewardedAware) {
      (this as RewardedAware).bindRewardedAd();
    }
  }

  @mustCallSuper
  @override
  void onClose() {
    if (this is BannerAware) {
      (this as BannerAware).disposeBanner();
    } else if (this is SharedBannerAware) {
      (this as SharedBannerAware).disposeBanner();
    }
    if (this is InterstitialAware) {
      (this as InterstitialAware).unbindInterstitialAd();
    }
    if (this is RewardedAware) {
      (this as RewardedAware).unbindRewardedAd();
    }

    adsCompleter?.close();
    super.onClose();
  }

  void clearAutoCompleteFrozenAdsTimer() {
    if (_autoCompleteFrozenAdsTimer != null) {
      removeTimer(_autoCompleteFrozenAdsTimer);
      Log.w("[$runtimeType] onPaused, remove _autoCompleteFrozenAdsTimer", tag: "Ads");
    }
  }

  @override
  @mustCallSuper
  void onResumed() {
    super.onResumed();
    if (this is SharedBannerAware) {
      (this as SharedBannerAware).processResumed();
    }
    if (adsCompleter?.isCompleted == false) {
      Log.d("[$runtimeType] onResumed, adsCompleter not complete!, start ADS Frozen check! waiting...", tag: "Ads");
      _autoCompleteFrozenAdsTimer = delayed(const Duration(seconds: 5), () {
        if (adsCompleter?.isCompleted == false) {
          Log.w(
              "[$runtimeType] onResumed, ADS Frozen!!! but adsCompleter is not completed, will complete with AdCause.noResponse",
              tag: "Ads");
          adsCompleter?.error(AdCause.noResponse);
        }
      });
    }
  }

  @override
  @mustCallSuper
  void onPaused() {
    if (this is SharedBannerAware) {
      (this as SharedBannerAware).processPaused();
    }
    clearAutoCompleteFrozenAdsTimer();
    super.onPaused();
  }
}
