package ads

import (
	"alpha/adDelivery/helper"
	"alpha/adDelivery/structure"
	"fmt"
	"math/rand"
	"net/http"

	config "alpha/configuration"
)

func GetInternalAds(outputData *structure.OutputData) bool {

	fmt.Println("GetInternalAds zone id", outputData.Zone_details.Zoneid)

	ads_info := LinkedAd(outputData)

	zninfo := outputData.Zone_details
	var house_ad bool

	adsFiltered, campaign_type := CheckAdCriteria(outputData.R, ads_info, zninfo, false)

	if len(adsFiltered) == 0 { // choose house ad

		adsFiltered, campaign_type = CheckAdCriteria(outputData.R, ads_info, zninfo, true)
		fmt.Println("25", house_ad)
		if len(adsFiltered) > 0 {
			fmt.Println("27")
			house_ad = true
		}
	}

	if len(adsFiltered) > 0 {

		fmt.Println("33")
		if outputData.VideoAdPod == 1 {

			adDetails := AdSelectAll(campaign_type, adsFiltered, zninfo)

			Html := VideoAdRenderAdPod(adDetails, zninfo, outputData.VideoAdPod_limit)

			if house_ad == true {

				outputData.Is_house_ad = true
				outputData.House_ad.Html = Html

			} else {

				outputData.Html = Html
				outputData.Internal_ad = true

			}

			return true

		} else {

			adDetails := AdSelect(campaign_type, adsFiltered, zninfo)

			if zninfo.Delivery == "6" || zninfo.Delivery == "7" {

				VideoAdRender(&adDetails, zninfo)

			} else if zninfo.Delivery == "10" {

				if outputData.Tag_type == "sdk" {

					outputData.HtmlInterface = AdRenderOutstreamVideoAdSDK(&adDetails, zninfo, outputData.R)
				} else {
					AdRenderOutstreamVideoAd(&adDetails, zninfo, outputData.R)
				}

			} else if zninfo.Delivery == "12" {
				AdRenderNativeAd(&adDetails, zninfo)
			} else {

				NormalAdRender(&adDetails, zninfo, outputData.Tag_type)
			}

			if house_ad == true {

				fmt.Println("80")
				outputData.Is_house_ad = true
				outputData.House_ad.Html = adDetails.Html
				outputData.House_ad.Ad_id = adDetails.Ad_id
				outputData.House_ad.Placement_id = adDetails.Placement_id
				outputData.House_ad.Imp_url = adDetails.Imp_url
				outputData.House_ad.Click_url = adDetails.Click_url

			} else {

				outputData.Html = adDetails.Html
				outputData.Internal_ad = true
				outputData.Ad_id = adDetails.Ad_id
				outputData.Placement_id = adDetails.Placement_id
				outputData.Imp_url = adDetails.Imp_url
				outputData.Click_url = adDetails.Click_url
			}

		}

		if outputData.Tag_type != "sdk" && outputData.Tag_type != "video" && outputData.Tag_type != "audio" {

			dmp_id := CookieValue(outputData.R, config.GetConfig("cookiename", "dmp"))

			if dmp_id == "" {

				if house_ad == true {

					outputData.House_ad.Html = outputData.House_ad.Html //+ getDmpPixelCode()
				} else {

					outputData.Html = outputData.Html //+ getDmpPixelCode()

				}
			}

		}

	}

	return true
}

func LinkedAd(outputData *structure.OutputData) map[string][]AdLinkedZone {

	zn := outputData.Zone_details

	a := AdLinkedZone{}

	var ad_xAds []AdLinkedZone
	var ad_ads []AdLinkedZone
	var ad_lAds []AdLinkedZone
	var ad_eAds []AdLinkedZone

	adsDetails := make(map[string][]AdLinkedZone)

	fmt.Println("zone id", zn.Zoneid)

	redisClients.GetKey("AdLinkedZone_"+fmt.Sprint(zn.Zoneid), &a)

	if a.Ad_id == 0 && a.Campaign_id == 0 {

		rows := InternalAdSelect(outputData)

		for rows.Next() {

			err := helper.Scan(&a, rows)

			redisClients.SetKey("AdLinkedZone_"+fmt.Sprint(zn.Zoneid), a)

			if err != nil {
				fmt.Println("Failed to run query", err)
			} else {

				if a.Campaign_priority == -1 {
					ad_xAds = append(ad_xAds, a)

				} else if a.Campaign_priority == 0 {

					ad_lAds = append(ad_lAds, a)

				} else if a.Campaign_priority == -2 {

					ad_eAds = append(ad_eAds, a)
				} else {
					ad_ads = append(ad_ads, a)
				}
			}

		}
		defer rows.Close()
	} else {

		if a.Campaign_priority == -1 {
			ad_xAds = append(ad_xAds, a)

		} else if a.Campaign_priority == 0 {

			ad_lAds = append(ad_lAds, a)

		} else if a.Campaign_priority == -2 {

			ad_eAds = append(ad_eAds, a)
		} else {
			ad_ads = append(ad_ads, a)
		}
	}

	adsDetails["xAds"] = ad_xAds
	adsDetails["lAds"] = ad_lAds
	adsDetails["eAds"] = ad_eAds
	adsDetails["ads"] = ad_ads

	return adsDetails

}

func AdSelect(campaign_type string, ads_info []AdLinkedZone, zone_info structure.ZoneDetails) AdDetails {

	fmt.Println("202")

	adDetails := AdDetails{}

	var totalPri int

	if campaign_type == "xAds" || campaign_type == "lAds" {

		totalPri = SetPriorityFromWeights(&ads_info)

	} else if campaign_type == "ads" {

		totalPri = 1
	}

	rt := rand.Intn(99999)

	random_num := float64(rand.Intn(rt)) / float64(rt)

	if float64(random_num) > float64(totalPri) {

		return adDetails
	}

	var low float64
	var high float64

	for _, aAds := range ads_info {

		if campaign_type == "ads" {

			aAds.PriorityFinal = 1
		}

		if aAds.PriorityFinal != 0 {

			low = high
			high += float64(aAds.PriorityFinal)

			if high > random_num && low < random_num {
				fmt.Println("242")
				return GetAd(aAds.Ad_id, adDetails)
			}
		}

	}
	fmt.Println("248")
	return adDetails

}

func AdSelectAll(campaign_type string, ads_info []AdLinkedZone, zone_info structure.ZoneDetails) []AdDetails {

	var allAdDetails []AdDetails

	adDetails := AdDetails{}

	var totalPri int

	if campaign_type == "xAds" || campaign_type == "lAds" {

		totalPri = SetPriorityFromWeights(&ads_info)

	} else if campaign_type == "ads" {

		totalPri = 1
	}

	rt := rand.Intn(99999)

	random_num := float64(rand.Intn(rt)) / float64(rt)

	if float64(random_num) > float64(totalPri) {
		allAdDetails = append(allAdDetails, adDetails)
	}

	for _, aAds := range ads_info {

		allAdDetails = append(allAdDetails, GetAd(aAds.Ad_id, adDetails))

	}

	fmt.Println("AdSelectAll", allAdDetails)

	return allAdDetails

}

func SetPriorityFromWeights(adsinfo *[]AdLinkedZone) int {

	ads_info := *adsinfo

	if len(ads_info) == 0 {
		return 0
	}

	aCampaignWeights := make(map[int]float64)
	aCampaignAdWeight := make(map[int]float64)

	for _, adinfo := range ads_info {

		if _, ok := aCampaignWeights[adinfo.Placement_id]; !ok {

			aCampaignWeights[adinfo.Placement_id] = float64(adinfo.Campaign_weight)
			aCampaignAdWeight[adinfo.Placement_id] = 0
		}

		aCampaignAdWeight[adinfo.Placement_id] += float64(adinfo.Weight)

	}

	for k, _ := range aCampaignWeights {

		if _, ok := aCampaignAdWeight[k]; ok {

			aCampaignWeights[k] /= aCampaignAdWeight[k]
		}

	}

	var totalPri float64

	for k, adinfo := range ads_info {
		ads_info[k].PriorityFinal = aCampaignWeights[adinfo.Placement_id] * float64(adinfo.Weight)
		totalPri += ads_info[k].PriorityFinal
	}

	if totalPri > 0 {

		for k, _ := range ads_info {
			ads_info[k].PriorityFinal /= totalPri

		}

		return 1

	}

	return 0

}

func CookieValue(r *http.Request, str string) string {

	cookie, err := r.Cookie(str)
	if err != nil {
		return ""

	}
	return cookie.Value

}
