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

import Foundation
import AppLovinSDK
import DTBiOSSDK

public class BannerAd: NSObject, MAAdViewAdDelegate, MAAdRevenueDelegate {
    var bannerAd: MAAdView? = nil

    var id: Int
    private var channel: FlutterMethodChannel
    var status: Int = AdStatus.CREATED

    var anchorOffset = 0.0
    var horizontalCenterOffset = 0.0
    var anchorType = 0

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

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

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

    static func orientationChanged(orientation: Int) {
        for ad in  allAds.values {
            ad.updateOrientation(orientation: orientation)
        }
    }
    
    init(id: Int, channel: FlutterMethodChannel) {
        self.id = id
        self.channel = channel
        self.anchorOffset = 0.0
        self.horizontalCenterOffset = 0.0
        self.anchorType = 0
        super.init()
        BannerAd.allAds[id] = self
    }

    func load(adUnitId: String, adAmazonSlotId: String, placement: String) {
        status = AdStatus.LOADING
        bannerAd = MAAdView(adUnitIdentifier: adUnitId)
        bannerAd?.placement = placement
        let delegate = UIApplication.shared.delegate as? FlutterAppDelegate
        let rootViewController = delegate?.window.rootViewController
        if let ad = bannerAd {
            ad.delegate = self
            ad.revenueDelegate = self
            ad.tag = id
            ad.isHidden = true
            ad.stopAutoRefresh()
            internalLoadAd(adAmazonSlotId: adAmazonSlotId)
        }
    }

    private func internalLoadAd(adAmazonSlotId: String) {
        if (!adAmazonSlotId.isEmpty) {
            let loader = DTBAdLoader()
            loader.setAdSizes([DTBAdSize(bannerAdSizeWithWidth: 320, height: 50, andSlotUUID: adAmazonSlotId)!])
            loader.loadAd(self)
        } else {
            bannerAd?.loadAd()
        }
    }

    func show() {
        if let bannerAd = bannerAd, bannerAd.isHidden {
            let delegate = UIApplication.shared.delegate as? FlutterAppDelegate
            let rootViewController = delegate?.window.rootViewController
            if let screen = rootViewController?.view, !screen.subviews.contains(bannerAd) {
                screen.addSubview(bannerAd)
                bannerAd.translatesAutoresizingMaskIntoConstraints = false
                
                let bottomAnchor: NSLayoutYAxisAnchor
                if #available(iOS 11.0, *) {
                    bottomAnchor = screen.safeAreaLayoutGuide.bottomAnchor
                } else {
                    bottomAnchor = screen.bottomAnchor
                }
                var offset = anchorOffset
                if (anchorType == 0) {
                    offset = -anchorOffset
                }
                let height = (UIDevice.current.userInterfaceIdiom == .pad) ? 90 : 50
                let width = UIScreen.main.bounds.width
                NSLog("Ads !!!!!!!!! anchorType +\(anchorType) 2222222 \(anchorType == 0)")
                NSLayoutConstraint.activate([
                    bannerAd.centerXAnchor.constraint(equalTo: screen.centerXAnchor, constant: CGFloat(horizontalCenterOffset)),
                    //anchorType == 0 ? guide.bottomAnchor : guide.topAnchor
                    bannerAd.bottomAnchor.constraint(equalTo: bottomAnchor, constant: CGFloat(offset)),
                    bannerAd.heightAnchor.constraint(equalToConstant: CGFloat(height)),
                    bannerAd.widthAnchor.constraint(equalToConstant: CGFloat(width))
                ])
            }
            bannerAd.isHidden = false
            bannerAd.startAutoRefresh()
        }
    }
    
    func updateOrientation(orientation: Int) {
        if let ad = bannerAd, let view = ad.viewWithTag(id) {
            let hidden = ad.isHidden
            ad.isHidden = true
            ad.stopAutoRefresh()
            view.removeFromSuperview()
            if (!hidden) {
                show()
            }
        }
    }

    func hide() {
        if let bannerAd = bannerAd, !bannerAd.isHidden{
            bannerAd.isHidden = true
            bannerAd.stopAutoRefresh()
        }
    }

    func dispose() {
        BannerAd.allAds.removeValue(forKey: id)
        guard let ba = bannerAd else {
            return
        }
        ba.stopAutoRefresh()
        ba.delegate = nil
        ba.revenueDelegate = nil
        ba.isHidden = true
        if let view = bannerAd!.viewWithTag(id) {
            view.removeFromSuperview()
        }
    }

    // MARK: MAAdDelegate Protocol

    public func didLoad(_ ad: MAAd) {
        let waterfallName = ad.waterfall.name
        status = AdStatus.LOADED
        channel.invokeMethod("onBannerAdLoaded", 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("onBannerAdLoadFailed",
                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) {
        channel.invokeMethod("onBannerAdDisplayed", arguments:
        ["id": id])
//        channel.invokeMethod("onBannerAdDisplayed", arguments:
//                                ["id" : id,
//                                 "ad_revenue" : ad.revenue ,
//                                 "ad_source" : ad.networkName,
//                                 "ad_format" : ad.format,
//                                 "ad_unit_name" : ad.adUnitIdentifier])
    }

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

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

    public func didExpand(_ ad: MAAd) {

    }

    public func didCollapse(_ ad: MAAd) {

    }

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

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