//
//  GuruRewardedVideoAd.swift
//  Pods
//
//  Created by mayue_work on 2020/3/12.
//

import Foundation
import UIKit
import AppLovinSDK
import DTBiOSSDK

public class RewardedVideoAd: NSObject, MARewardedAdDelegate, MAAdRevenueDelegate {

    var rewardedAd: MARewardedAd? = nil
    var isFirstLoad = true
    var id: Int
    private var channel: FlutterMethodChannel
    var status: Int = AdStatus.CREATED

    private static var allAds: [Int: RewardedVideoAd] = [:]

    static func createRewardedVideo(id: Int, channel: FlutterMethodChannel) -> RewardedVideoAd {
        if let ad = getAdForId(id: id) {
            return ad
        } else {
            return RewardedVideoAd(id: id, channel: channel)
        }
    }

    static func getAdForId(id: Int) -> RewardedVideoAd? {
        return allAds[id]
    }

    init(id: Int, channel: FlutterMethodChannel) {
        self.id = id
        self.channel = channel
        super.init()
        RewardedVideoAd.allAds[id] = self
    }

    func load(adUnitId: String, amazonSlotId: String) {
        status = AdStatus.LOADING
        rewardedAd = MARewardedAd.shared(withAdUnitIdentifier: adUnitId)
        rewardedAd?.delegate = self
        rewardedAd?.revenueDelegate = self
         // If first load - load ad from Amazon's SDK, then load ad for MAX
        if isFirstLoad && amazonSlotId.isEmpty == false{
            isFirstLoad = false
            let adLoader = DTBAdLoader()
            adLoader.setAdSizes([DTBAdSize(videoAdSizeWithPlayerWidth: 320, height: 480, andSlotUUID: amazonSlotId)!])
            adLoader.loadAd(self)
        }
        else{
            rewardedAd?.load()
        }
        // Load the first ad
        rewardedAd?.load()
    }

    func show(placement: String) -> Bool {
        if let ad = rewardedAd,
           ad.isReady {
            ad.show(forPlacement: placement)
            return true
        }
        return false
    }

    func dispose() {
    }
    
    func getState() -> Int {
        switch (status) {
        case AdStatus.LOADED:
            if (rewardedAd?.isReady == true) {
                return status;
            } else {
                return AdStatus.FAILED;
            }
        case AdStatus.LOADING:
            if (rewardedAd?.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("onRewardedVideoAdLoaded", 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("onRewardedVideoAdLoadFailed",
                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("onRewardedVideoAdDisplayed", arguments: arguments)
    }

    public func didClick(_ ad: MAAd) {
        channel.invokeMethod("onRewardedVideoAdClicked", arguments: ["id": id])
    }

    public func didHide(_ ad: MAAd) {
        // Rewarded ad is hidden. Pre-load the next ad
//        rewardedAd?.load()
        status = AdStatus.CREATED
        channel.invokeMethod("onRewardedVideoAdHidden", 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("onRewardedVideoAdDisplayFailed",
                             arguments: ["id": id,"errorCode": error.code.rawValue])
    }

    // MARK: MARewardedAdDelegate Protocol

    public func didStartRewardedVideo(for ad: MAAd) {
        channel.invokeMethod("onRewardedVideoStarted", arguments: ["id": id])
    }

    public func didCompleteRewardedVideo(for ad: MAAd) {
        channel.invokeMethod("onRewardedVideoCompleted", arguments: ["id": id])
    }

    public func didRewardUser(for ad: MAAd, with reward: MAReward) {
        // Rewarded ad was displayed and user should receive the reward
        channel.invokeMethod("onRewardedVideoUserRewarded",
                arguments: ["id": id,
                            "rewardLabel": reward.label,
                            "rewardAmount": reward.amount])
    }

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

    }

}

extension RewardedVideoAd: DTBAdCallback{
    public  func onSuccess(_ adResponse: DTBAdResponse!){
        // `interstitialAd` is your instance of MAInterstitialAd
        NSLog("RewardAd amazon load success")
        rewardedAd?.setLocalExtraParameterForKey("amazon_ad_response", value: adResponse)
        rewardedAd?.load()
    }

    public  func onFailure(_ error: DTBAdError, dtbAdErrorInfo: DTBAdErrorInfo!){
        // `interstitialAd` is your instance of MAInterstitialAd
        NSLog("RewardAd amazon load failed \(error.rawValue)")
        rewardedAd?.setLocalExtraParameterForKey("amazon_ad_error", value: dtbAdErrorInfo)
        rewardedAd?.load()
    }
}
