﻿using System;
using UnityEngine;

public class AdManager : MonoBehaviour
{
    private static AdManager _instance;
    private static readonly object _lock = new object();

    public static AdManager Instance
    {
        get
        {
            if (_instance == null)
            {
                lock (_lock)
                {
                    if (_instance == null)
                    {
                        var gameObject = new GameObject(nameof(AdManager));
                        _instance = gameObject.AddComponent<AdManager>();
                        DontDestroyOnLoad(gameObject);
                    }
                }
            }
            return _instance;
        }
    }
    public event Action OnInitializedEvent;

    public event Action OnInterstitialAdShowFailedEvent;
    public event Action OnInterstitialAdClosedEvent;

    public event Action OnRewardedAdShowFailedEvent;
    public event Action OnRewardedAdFinishedEvent;
    public event Action OnRewardedAdClosedEvent;

    private bool IsInitialized { get; set; }

    private bool _isFirstSdkInitialized;
    private bool _isSecondSdkInitialized;

    private ISdkProvider _firstSdkProvider;
    private ISdkProvider _secondSdkProvider;

    private IBannerAdController _bannerAdController;
    private IRewardedAdController _rewardedAdController;
    private IInterstitialAdController _interstitialAdController;

    public void Init()
    {
        AdHelper.Log("[AdManager] [Method] Init()");

        _firstSdkProvider = new LevelPlaySdkProvider();
        _firstSdkProvider.OnInitialized += (_, _) => _isFirstSdkInitialized = true;
        _firstSdkProvider.Initialize();

        _secondSdkProvider = new BidonSdkProvider();
        _secondSdkProvider.OnInitialized += (_, _) => _isSecondSdkInitialized = true;
        _secondSdkProvider.Initialize();
    }

    private void Update()
    {
        if (!IsInitialized && _isFirstSdkInitialized && _isSecondSdkInitialized)
        {
            IsInitialized = true;

            _bannerAdController = new PostBidBannerAdController(_firstSdkProvider?.GetBannerAdProvider(), _secondSdkProvider?.GetBannerAdProvider());
            _interstitialAdController = new PostBidInterstitialAdController(_firstSdkProvider?.GetInterstitialAdProvider(), _secondSdkProvider?.GetInterstitialAdProvider());
            _rewardedAdController = new PostBidRewardedAdController(_firstSdkProvider?.GetRewardedAdProvider(), _secondSdkProvider?.GetRewardedAdProvider());

            _interstitialAdController.OnAdShowFailed += OnInterstitialAdShowFailed;
            _interstitialAdController.OnAdClosed += OnInterstitialAdClosed;

            _rewardedAdController.OnAdShowFailed += OnRewardedAdShowFailed;
            _rewardedAdController.OnAdClosed += OnRewardedAdClosed;

            OnInitializedEvent?.Invoke();
        }
    }

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

        _bannerAdController?.ShowBanner();
    }

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

        _bannerAdController?.HideBanner();
    }

    public void ShowInterstitialAd(string placement)
    {
        if (IsInterstitialAdAvailable(placement))
        {
            AdHelper.Log($"[AdManager] [Method] ShowInterstitial(placement: {placement})");

            _interstitialAdController?.ShowInterstitial(placement);
        }
    }

    public void ShowRewardedAd(string placement)
    {
        if (IsRewardedAdAvailable())
        {
            AdHelper.Log($"[AdManager] [Method] ShowRewardedAd(placement: {placement})");

            _rewardedAdController?.ShowRewarded(placement);
        }
    }

    public bool IsRewardedAdAvailable()
    {
        AdHelper.Log("[AdManager] [Method] IsRewardedAdAvailable()");

        return _rewardedAdController?.IsLoaded() ?? false;
    }

    public bool IsInterstitialAdAvailable(string placement)
    {
        AdHelper.Log($"[AdManager] [Method] IsInterstitialAdAvailable(placement: {placement})");

        return Application.internetReachability != NetworkReachability.NotReachable
                && (_interstitialAdController?.IsLoaded() ?? false);
    }

    private void OnInterstitialAdShowFailed(object sender, EventArgs e)
    {
        AdHelper.Log("[AdManager] OnInterstitialAdShowFailedEvent");

        OnInterstitialAdShowFailedEvent?.Invoke();
    }

    private void OnInterstitialAdClosed(object sender, EventArgs e)
    {
        AdHelper.Log("[AdManager] OnInterstitialAdClosedEvent");

        OnInterstitialAdClosedEvent?.Invoke();
    }

    private void OnRewardedAdShowFailed(object sender, EventArgs e)
    {
        AdHelper.Log("[AdManager] OnRewardedAdShowFailedEvent()");

        OnRewardedAdShowFailedEvent?.Invoke();
    }

    private void OnRewardedAdClosed(object sender, bool shouldReward)
    {
        AdHelper.Log($"[AdManager] OnRewardedAdClosedEvent(bool finished:{shouldReward})");

        if (shouldReward) OnRewardedAdFinishedEvent?.Invoke();
        OnRewardedAdClosedEvent?.Invoke();
    }
}
