using System;
using Unity.Services.LevelPlay;
using LevelPlayAdSize = com.unity3d.mediation.LevelPlayAdSize;
using LevelPlayBannerPosition = com.unity3d.mediation.LevelPlayBannerPosition;

public class LevelPlayBannerAdProvider : IBannerAdProvider
{
    public string Name { get => "levelplay"; }

    public event EventHandler<double> OnAdLoaded;
    public event EventHandler<string> OnAdLoadFailed;
    public event EventHandler OnAdShown;
    public event EventHandler<AdRevenueReceivedEventArgs> OnAdRevenueReceived;

    private string LevelPlayBannerAdUnitId { get; }

    private LevelPlayBannerAd BannerAd { get; set; }

    public LevelPlayBannerAdProvider(string adUnitId)
    {
        AdHelper.Log("[LevelPlayBannerAdProvider] [Constructor] LevelPlayBannerAdProvider()");

        LevelPlayBannerAdUnitId = adUnitId;

        InstantiateBannerAd();
    }

    public void InstantiateBannerAd()
    {
        AdHelper.Log("[LevelPlayBannerAdProvider] [Method] InstantiateBannerAd()");

        if (BannerAd != null)
        {
            UnsubscribeFromBannerAdEvents(BannerAd);
            BannerAd.DestroyAd();
        }

        BannerAd = new LevelPlayBannerAd(LevelPlayBannerAdUnitId, LevelPlayAdSize.BANNER, LevelPlayBannerPosition.BottomCenter, null, false);
        BannerAd?.PauseAutoRefresh();
        SubscribeToBannerAdEvents(BannerAd);
    }

    public void LoadBannerAd(double priceFloor = 0d)
    {
        AdHelper.Log("[LevelPlayBannerAdProvider] [Method] LoadBannerAd()");

        BannerAd?.LoadAd();
    }

    public void NotifyLoss(string winnerDemandId, double ecpm)
    {
        AdHelper.Log($"[LevelPlayBannerAdProvider] [Method] NotifyLoss(winner: {winnerDemandId}, ecpm: {ecpm})");
    }

    public void NotifyWin()
    {
        AdHelper.Log("[LevelPlayBannerAdProvider] [Method] NotifyWin()");
    }

    public void ShowBannerAd()
    {
        AdHelper.Log("[LevelPlayBannerAdProvider] [Method] ShowBannerAd()");

        BannerAd?.ShowAd();
    }

    public void HideBannerAd()
    {
        AdHelper.Log("[LevelPlayBannerAdProvider] [Method] HideBannerAd()");

        BannerAd?.HideAd();
    }

    private void SubscribeToBannerAdEvents(LevelPlayBannerAd ad)
    {
        if (ad == null) return;

        AdHelper.Log("[LevelPlayBannerAdProvider] [Method] SubscribeToBannerAdEvents()");

        ad.OnAdLoaded += OnLevelPlayBannerAdLoaded;
        ad.OnAdLoadFailed += OnLevelPlayBannerAdLoadFailed;
        ad.OnAdDisplayed += OnLevelPlayBannerAdDisplayed;
    }

    private void UnsubscribeFromBannerAdEvents(LevelPlayBannerAd ad)
    {
        if (ad == null) return;

        AdHelper.Log("[LevelPlayBannerAdProvider] [Method] UnsubscribeFromBannerAdEvents()");

        ad.OnAdLoaded -= OnLevelPlayBannerAdLoaded;
        ad.OnAdLoadFailed -= OnLevelPlayBannerAdLoadFailed;
        ad.OnAdDisplayed -= OnLevelPlayBannerAdDisplayed;
    }

    private void OnLevelPlayBannerAdLoaded(LevelPlayAdInfo adInfo)
    {
        double ecpm = AdHelper.GetRoundedEcpm((adInfo.Revenue ?? 0d) * 1000);
        AdHelper.Log($"[LevelPlayBannerAdProvider] [Method] OnLevelPlayBannerAdLoaded(ecpm: {ecpm}). Revenue is {adInfo.Revenue}");

        OnAdLoaded?.Invoke(this, ecpm);
    }

    private void OnLevelPlayBannerAdLoadFailed(LevelPlayAdError error)
    {
        AdHelper.Log("[LevelPlayBannerAdProvider] [Method] OnLevelPlayBannerAdLoadFailed()");

        OnAdLoadFailed?.Invoke(this, error.ToString());
    }

    private void OnLevelPlayBannerAdDisplayed(LevelPlayAdInfo adInfo)
    {
        AdHelper.Log("[LevelPlayBannerAdProvider] [Method] OnLevelPlayBannerAdDisplayed()");

        OnAdShown?.Invoke(this, EventArgs.Empty);

        var info = new AdInfo
        {
            AdType = "Banner",
            AdUnitId = adInfo.AdUnitId,
            CurrencyCode = "USD",
            MediationId = Name,
            NetworkAdUnitId = adInfo.InstanceId,
            NetworkName = adInfo.AdNetwork,
            Revenue = adInfo.Revenue ?? 0d,
            RevenuePrecision = adInfo.Precision,
        };
        OnAdRevenueReceived?.Invoke(this, new AdRevenueReceivedEventArgs(info));
    }
}
