//
//  File.swift
//  guru_applovin_flutter
//
//  Created by yaqi liu on 2020/3/13.
//

import Foundation
import AppLovinSDK
import DTBiOSSDK

public class InterstitialAd: NSObject, MAAdDelegate, MAAdRevenueDelegate {


    var interstitialAd: MAInterstitialAd? = nil
    
    var id: Int
    private var channel: FlutterMethodChannel
    var status: Int = AdStatus.CREATED
    
    var isFirstLoad = true
    
    private static var allAds: [Int : InterstitialAd] = [:]
    
    static func createInterstitialAd(id: Int, channel: FlutterMethodChannel) -> InterstitialAd {
        if let ad = getAdForId(id: id) {
            return ad
        } else {
            return InterstitialAd(id: id, channel: channel)
        }
    }
    
    static func getAdForId(id: Int) -> InterstitialAd? {
        return allAds[id]
    }
    
    init(id: Int, channel: FlutterMethodChannel) {
        self.id = id
        self.channel = channel
        super.init()
        InterstitialAd.allAds[id] = self
    }
    
    func load(adUnitId: String, adAmazonSlotId: String) {
        status = AdStatus.LOADING
        interstitialAd = MAInterstitialAd(adUnitIdentifier: adUnitId)
        interstitialAd?.delegate = self
        interstitialAd?.revenueDelegate = self
        
        if (isFirstLoad && !adAmazonSlotId.isEmpty) {
            isFirstLoad = false
            let loader = DTBAdLoader()
            loader.setAdSizes([DTBAdSize(videoAdSizeWithPlayerWidth: 320, height: 480, andSlotUUID: adAmazonSlotId)!])
            loader.loadAd(self)
        } else {
            interstitialAd?.load()
        }
        
    }
    
    func show(placement: String) -> Bool {
        if let ad = interstitialAd,
           ad.isReady {
            ad.show(forPlacement: placement)
            return true
        }
        return false
    }

    func dispose() {
    }
    
    func getState() -> Int {
        switch (status) {
        case AdStatus.LOADED:
            if (interstitialAd?.isReady == true) {
                return status;
            } else {
                return AdStatus.FAILED;
            }
        case AdStatus.LOADING:
            if (interstitialAd?.isReady == true) {
                return AdStatus.LOADED;
            } else {
                return status;
            }
        default:
            return status;
        }
    }
    
    // MARK: MAAdDelegate Protocol
    public func didLoad(_ ad: MAAd) {
        // Rewarded ad is ready to be shown. '[self.rewardedAd isReady]' will now return 'YES'
        let waterfallName = ad.waterfall.name
        status = AdStatus.LOADED
        channel.invokeMethod("onInterstitialAdLoaded", arguments: ["id" : id,
                                                                   "ad_waterfall_name": waterfallName] as [String : Any])
    }
    
    public func didFailToLoadAd(forAdUnitIdentifier adUnitIdentifier: String, withError error: MAError) {
        let waterfallName = error.waterfall?.name ?? "Unknown"
        status = AdStatus.FAILED
        channel.invokeMethod("onInterstitialAdLoadFailed",
                             arguments: ["id" : id,
                                         "errorCode" : error.code.rawValue,
                                         "ad_waterfall_name": waterfallName] as [String : Any])

        
        // Rewarded ad failed to load. We recommend re-trying in 3 seconds.
        //        DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
        //            self.rewardedAd?.load()
        //        }
    }
    
    public func didDisplay(_ ad: MAAd) {
        let arguments: [String: Any] = ["id" : id,
                                        "ad_revenue": ad.revenue,
                                        "ad_source": ad.networkName,
                                        "ad_format": AdHelper.toFormatName(ad.format),
                                        "ad_unit_name": ad.adUnitIdentifier]
        channel.invokeMethod("onInterstitialAdDisplayed", arguments: arguments)
    }
    
    public func didClick(_ ad: MAAd) {
        channel.invokeMethod("onInterstitialAdClicked", arguments: ["id" : id])
    }
    
    public func didHide(_ ad: MAAd) {
        // Rewarded ad is hidden. Pre-load the next ad
        //        rewardedAd?.load()
        status = AdStatus.CREATED
        channel.invokeMethod("onInterstitialAdHidden", arguments: ["id" : id])
    }
    
    public func didFail(toDisplay ad: MAAd, withError error: MAError)
    {
        // Rewarded ad failed to display. We recommend loading the next ad
        //        rewardedAd?.load()
        status = AdStatus.FAILED
        channel.invokeMethod("onInterstitialAdDisplayFailed",
                             arguments: ["id" : id,
                                         "errorCode" : error.code.rawValue])
    }

    public func didPayRevenue(for ad: MAAd) {
        channel.invokeMethod("onAdImpression",
                arguments: ["payload": AdHelper.toAdPayload(ad)]
        )
    }

}

extension InterstitialAd: DTBAdCallback {
    
    public func onSuccess(_ adResponse: DTBAdResponse!) {
        interstitialAd?.setLocalExtraParameterForKey("amazon_ad_response", value: adResponse)
        interstitialAd?.load()
    }
    
    public func onFailure(_ error: DTBAdError, dtbAdErrorInfo: DTBAdErrorInfo!) {
        interstitialAd?.setLocalExtraParameterForKey("amazon_ad_error", value: dtbAdErrorInfo)
        interstitialAd?.load()
    }
}
