import GoogleMobileAds

protocol AMBGenericAd {
    func isLoaded() -> Bool
    func load(_ ctx: AMBContext)
    func show(_ ctx: AMBContext)
    func hide(_ ctx: AMBContext)
}

extension AMBGenericAd {
    func hide(_ ctx: AMBContext) {
        ctx.success()
    }
}

class AMBAdBase: NSObject {
    static var ads = [Int: AMBAdBase]()

    let id: Int
    let adUnitId: String

    var plugin: AMBPlugin {
        return AMBContext.plugin
    }

    init(id: Int, adUnitId: String) {
        self.id = id
        self.adUnitId = adUnitId

        super.init()

        AMBAdBase.ads[id] = self
    }

    convenience init?(_ ctx: AMBContext) {
        guard let id = ctx.optId(),
              let adUnitId = ctx.optAdUnitID()
        else {
            return nil
        }
        self.init(id: id, adUnitId: adUnitId)
    }

    deinit {
        let key = self.id
        DispatchQueue.main.async {
            AMBAdBase.ads.removeValue(forKey: key)
        }
    }

    func emit(_ eventName: String) {
        self.emit(eventName, ["adId": self.id])
    }

    func emit(_ eventName: String, _ error: Error) {
        self.emit(eventName, ["message": error.localizedDescription])
    }

    func emit(_ eventName: String, _ reward: GADAdReward) {
        self.emit(eventName, [
            "reward": [
                "amount": reward.amount,
                "type": reward.type
            ]
        ])
    }

    func emit(_ eventName: String, _ adSize: GADAdSize) {
        self.emit(eventName, [
            "size": [
                "width": adSize.size.width,
                "height": adSize.size.height
            ]
        ])
    }

    func emit(_ eventName: String, _ data: [String: Any]) {
        var d: [String: Any] = ["adId": self.id]
        d.merge(data) { (current, _) in current }
        plugin.emit(eventName, data: d)
    }

    func emit(_ eventName: String, _ nativeAd: GADNativeAd) {
        plugin.emit(eventName, data: ["adId": nativeAd.hashValue])
    }
}
