package com.composition.android.lib.ad.widget

import android.content.Context
import android.content.res.TypedArray
import android.util.AttributeSet
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import androidx.core.view.isVisible
import androidx.lifecycle.findViewTreeLifecycleOwner
import androidx.lifecycle.lifecycleScope
import com.composition.android.lib.ad.AdLoad
import com.composition.android.lib.ad.AdManager
import com.composition.android.lib.ad.AdUnitConfigManager
import com.composition.android.lib.ad.R
import com.composition.android.lib.ad.basic.AdResult
import com.composition.android.lib.ad.basic.Advertisers
import com.composition.android.lib.ad.basic.NativeAdViewHolder
import com.composition.android.lib.ad.basic.buildAdNativeViewHolder
import com.composition.android.lib.ad.impl.NormalAdListener
import com.composition.android.lib.ad.util.adLogE
import com.composition.android.lib.ad.util.getActivityFromView
import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.launch

/**
 * @classname:
 * @author: LiuXiaoLong
 * @date: 2022/9/7
 * description: 自定义的原生广告View, 通过在xml中的配置，view中进行加载广告并展示
 *
 * <NativeAdView
 *  //对应的NativeAdViewHolder view配置，设置view的id..还有其他的，具体查看attr.xml/NativeAdView
 *  app:ad_view_title="@id/tv_ad_title"
 *  app:ad_view_title_desc="..."
 *
 *  //不同广告厂商的原生广告根布局，在每个库中都会默认定义一个，或者自行添加
 *  admob : layout_admob_native_ad_view_root.xml   gms.NativeAdView
 *
 *  app:native_admob_advertisers_root_view="@layout/layout_admob_native_ad_view_root"
 *  app:native_csj_advertisers_root_view="xxx"
 *  app:native_app_lovin_advertisers_root_view="xxx"
 *  app:native_custom_advertisers_root_view="xxx"
 *
 * >
 *
 *     //具体的原生广告view布局
 *     <TextView
 *      android:id="@+id/tv_ad_title"
 *     />
 *
 * </NativeAdView>
 *
 *
 *
 */
class NativeAdView : LinearLayout {

    /**
     * 广告位名称
     */
    private var adSlotName: String = ""

    private var viewHolder: NativeAdViewHolder? = null

    private var adResult: AdResult? = null

    /**
     * NativeAdViewHolder 中view的id -------->
     */
    private var adTitleViewId: Int = 0

    private var adTitleDescViewId: Int = 0

    private var adIconViewId = 0

    private var adMediaContentViewId = 0

    private var adCallToActionViewId = 0

    private var adAdvertisersLogoViewId = 0

    private var adCloseIconViewId = 0

    private var advertisersContainerView: ViewGroup? = null

    /**
     * <-----------
     */

    private var autoPopulate = true

    constructor(context: Context?) : super(context)
    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
    constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) {
        init(attrs)
    }

    private fun init(attrs: AttributeSet?) {
        val typedArray: TypedArray = context.obtainStyledAttributes(attrs, R.styleable.NativeAdView)
        //获取到配置的广告名称
        adSlotName = typedArray.getString(R.styleable.NativeAdView_ad_slot_name) ?: ""

        val adUnitBean = AdUnitConfigManager.instance.getAdUnitBySlotName(adSlotNames = listOf(adSlotName)).getOrNull(0)
        if (adUnitBean == null) {
            adLogE(AdManager.TAG, "配置的广告位数据不存在, 当前广告位:${adSlotName}")
        }
        when (adUnitBean?.getAdvertisers()) {
            Advertisers.Admob -> attachedAdvertisersNativeAdViewToRoot(typedArray, R.styleable.NativeAdView_ad_admob_native_ad_view_layout)
            Advertisers.CSJ, Advertisers.AppLovinMax -> advertisersContainerView = this
            Advertisers.GroMore -> attachedAdvertisersNativeAdViewToRoot(typedArray, R.styleable.NativeAdView_ad_gro_more_tt_native_ad_view_layout)
            Advertisers.CUSTOM -> advertisersContainerView = this
            else -> {}
        }

        adTitleViewId = typedArray.getResourceId(R.styleable.NativeAdView_ad_view_title_id, 0)
        adTitleDescViewId = typedArray.getResourceId(R.styleable.NativeAdView_ad_view_title_desc_id, 0)
        adIconViewId = typedArray.getResourceId(R.styleable.NativeAdView_ad_view_icon_id, 0)
        adMediaContentViewId = typedArray.getResourceId(R.styleable.NativeAdView_ad_view_media_content_group_id, 0)
        adCallToActionViewId = typedArray.getResourceId(R.styleable.NativeAdView_ad_view_call_to_action_id, 0)
        adAdvertisersLogoViewId = typedArray.getResourceId(R.styleable.NativeAdView_ad_view_advertisers_logo_id, 0)
        adCloseIconViewId = typedArray.getResourceId(R.styleable.NativeAdView_ad_view_close_ad_icon_id, 0)
        autoPopulate = typedArray.getBoolean(R.styleable.NativeAdView_ad_auto_populate, true)

        typedArray.recycle()
    }


    override fun addView(child: View?, index: Int, params: ViewGroup.LayoutParams?) {

        val root = getChildAt(0)
        if (childCount != 0 && root is ViewGroup) {
            //这里会把xml 中写的自定义布局加入进来
            (getChildAt(0) as ViewGroup).addView(child, index, params)
            Log.e("测试", "if true, child:${child?.javaClass?.simpleName}")
        } else {
            //把广告商的View先加进来
            super.addView(child, index, params)
            Log.e("测试", "if else, child:${child?.javaClass?.simpleName}")
        }
    }


    override fun onAttachedToWindow() {
        super.onAttachedToWindow()
        initViewHolder()
        if (autoPopulate) {
            loadAd()
        }
    }

    override fun onDetachedFromWindow() {
        super.onDetachedFromWindow()
        destroyAd()
    }

    private fun initViewHolder() {
        if (viewHolder == null) {
            viewHolder = buildAdNativeViewHolder {
                this.customLayoutRootView = advertisersContainerView
                this.titleView = findViewById(adTitleViewId)
                this.titleDescView = findViewById(adTitleDescViewId)
                this.iconView = findViewById(adIconViewId)
                this.callActionButtonView = findViewById(adCallToActionViewId)
                this.contentMediaViewGroup = findViewById(adMediaContentViewId)
                this.advertiserLogoImageView = findViewById(adAdvertisersLogoViewId)
                this.dislikeView = findViewById(adCloseIconViewId)
                this.activity = getActivityFromView()
                this.adListener = object : NormalAdListener() {
                    override fun onAdDisLike() {
                        super.onAdDisLike()
                        isVisible = false
                        advertisersContainerView?.removeAllViews()
                    }
                }
            }
        }
    }

    private fun attachedAdvertisersNativeAdViewToRoot(typedArray: TypedArray, id: Int) {
        typedArray.getResourceId(id, -1).let {
            if (it != -1) {
                Log.e("测试", "开始解析厂商布局")
                LayoutInflater.from(context).inflate(it, this, true) as ViewGroup
                val root = getChildAt(0) as ViewGroup
                advertisersContainerView = root
                Log.e("测试", "厂商布局解析完成: root${root.javaClass.simpleName}")
            }
        }
    }

    fun loadAd() {
        findViewTreeLifecycleOwner()?.lifecycleScope?.launch {
            destroyAd()
            adResult = AdLoad.loadAd(context, adSlotName).firstOrNull()
            initViewHolder()
            if (adResult != null && adResult is AdResult.Success && viewHolder != null && advertisersContainerView != null) {
                AdLoad.populateNativeAdView(context, adResult as AdResult.Success, viewHolder!!, advertisersContainerView!!)
                isVisible = true
            }
            if (advertisersContainerView == null){
                adLogE(tag = "原生广告NativeAdView", msg = "厂商的原生广告容器为null, 请指定 ad_admob_native_ad_view_layout 或 其他属性")
            }
        }
    }


    private fun destroyAd() {
        AdLoad.destroyAd(adResult)
    }


    /**
     * 可以不使用View中的自动加载，在这里进行自行填充，非常适用于在RecyclerView中使用
     */
    fun populateNativeAd(adResult: AdResult.Success) {
        initViewHolder()
        if (viewHolder != null && advertisersContainerView != null) {
            AdLoad.populateNativeAdView(context, adResult, viewHolder!!, advertisersContainerView!!)
        }
    }


    fun setAdSlotNameAndLoadAd(adSlotName: String) {
        this.adSlotName = adSlotName
        loadAd()
    }


    /**
     * 刷新广告
     */
    fun refreshAd() {
        loadAd()
    }

    fun removeAd() {
        isVisible = false
    }

}