/**
 * Project Name:tuia-youtui-web<br>
 * File Name:MainMeetBOImpl.java<br>
 * Package Name:com.duiba.tuia.youtui.web.bo.impl<br>
 * Date:2017年3月3日上午11:28:50<br>
 * Copyright (c) 2017, duiba.com.cn All Rights Reserved.<br>
 */

package com.duiba.tuia.youtui.web.bo.impl;

import cn.com.duiba.tuia.activity.center.api.constant.BalanceRecordType;
import cn.com.duiba.tuia.activity.center.api.constant.BalanceType;
import cn.com.duiba.tuia.activity.center.api.constant.DirectBlockType;
import cn.com.duiba.tuia.activity.center.api.constant.IdType;
import cn.com.duiba.tuia.activity.center.api.constant.LoginType;
import cn.com.duiba.tuia.activity.center.api.constant.PageType;
import cn.com.duiba.tuia.activity.center.api.constant.SlotLoginType;
import cn.com.duiba.tuia.activity.center.api.dto.ActivityPluginDto;
import cn.com.duiba.tuia.activity.center.api.dto.GuidePageBlockDto;
import cn.com.duiba.tuia.activity.center.api.dto.GuidePageDto;
import cn.com.duiba.tuia.activity.center.api.dto.GuidePageRelationDto;
import cn.com.duiba.tuia.activity.center.api.dto.GuidePageSkinDto;
import cn.com.duiba.tuia.activity.center.api.dto.NickNameDto;
import cn.com.duiba.tuia.activity.center.api.dto.TuiaActivityDto;
import cn.com.duiba.tuia.activity.center.api.dto.consumer.ConsumerCache;
import cn.com.duiba.tuia.activity.center.api.dto.consumer.ConsumerDto;
import cn.com.duiba.tuia.activity.center.api.dto.consumer.req.BalanceRecordAdd;
import cn.com.duiba.tuia.activity.center.api.util.CollectionTool;
import cn.com.duiba.tuia.activity.center.api.util.EntityUtil;
import cn.com.duiba.tuia.ssp.center.api.dto.RspActivityCenterDto;
import cn.com.duiba.tuia.ssp.center.api.dto.SlotDto;
import cn.com.duiba.wolf.utils.BeanUtils;
import cn.com.tuia.advert.model.AdvertDirectDto;
import com.alibaba.fastjson.JSONObject;
import com.duiba.tuia.youtui.web.bo.MainMeetBO;
import com.duiba.tuia.youtui.web.constant.CacheKey;
import com.duiba.tuia.youtui.web.constant.Constants;
import com.duiba.tuia.youtui.web.constant.PreSource;
import com.duiba.tuia.youtui.web.embed.DcmBuilder;
import com.duiba.tuia.youtui.web.embed.DpmBuilder;
import com.duiba.tuia.youtui.web.embed.DsmBuilder;
import com.duiba.tuia.youtui.web.embed.GameHallEmbed;
import com.duiba.tuia.youtui.web.embed.WalletEmbed;
import com.duiba.tuia.youtui.web.exception.ActivityException;
import com.duiba.tuia.youtui.web.model.ActivityForActCenterVO;
import com.duiba.tuia.youtui.web.model.AdvertVO;
import com.duiba.tuia.youtui.web.model.UserAccount;
import com.duiba.tuia.youtui.web.model.direct.ActivityBlock;
import com.duiba.tuia.youtui.web.model.direct.AdvertBlock;
import com.duiba.tuia.youtui.web.model.direct.Block;
import com.duiba.tuia.youtui.web.model.direct.DirectBlock;
import com.duiba.tuia.youtui.web.model.direct.EmbeddedPluginBlock;
import com.duiba.tuia.youtui.web.model.direct.GameBlock;
import com.duiba.tuia.youtui.web.model.direct.MainMeetBlock;
import com.duiba.tuia.youtui.web.model.direct.UrlBlock;
import com.duiba.tuia.youtui.web.model.mainmeet.BlockRelation;
import com.duiba.tuia.youtui.web.model.mainmeet.BlockRsp;
import com.duiba.tuia.youtui.web.model.req.DirectPageReq;
import com.duiba.tuia.youtui.web.model.req.IndexReq;
import com.duiba.tuia.youtui.web.model.rsp.DirectBlockRsp;
import com.duiba.tuia.youtui.web.model.rsp.DirectPageRsp;
import com.duiba.tuia.youtui.web.model.rsp.GameHallAnnouncementRsp;
import com.duiba.tuia.youtui.web.model.rsp.GetActivitysRsp;
import com.duiba.tuia.youtui.web.service.ActivityEngineService;
import com.duiba.tuia.youtui.web.service.ActivityService;
import com.duiba.tuia.youtui.web.service.AdvertService;
import com.duiba.tuia.youtui.web.service.ConsumerService;
import com.duiba.tuia.youtui.web.service.DirectPageSourceService;
import com.duiba.tuia.youtui.web.service.GuidePageService;
import com.duiba.tuia.youtui.web.service.SlotService;
import com.duiba.tuia.youtui.web.service.UserBalanceService;
import com.duiba.tuia.youtui.web.tool.ActivityUtil;
import com.duiba.tuia.youtui.web.tool.CachedKeyUtils;
import com.duiba.tuia.youtui.web.tool.DomainConstantUtil;
import com.duiba.tuia.youtui.web.tool.DomainUtil;
import com.duiba.tuia.youtui.web.tool.DpmInfo;
import com.duiba.tuia.youtui.web.tool.DsmInfo;
import com.duiba.tuia.youtui.web.tool.PathUtil;
import com.duiba.tuia.youtui.web.tool.RequestLocal;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Queues;
import com.google.common.collect.Sets;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.RandomUtils;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.stream.Collectors;

/**
 * ClassName: MainMeetBOImpl <br/>
 * date: 2017年3月3日 上午11:28:50 <br/>
 *
 * @author youhaijun
 * @since JDK 1.6
 */
@Service
public class MainMeetBOImpl implements MainMeetBO {

    protected Logger logger = LoggerFactory.getLogger(getClass());

    private static final String ST_INFO_DPM_EXPOSURE = "st_info_dpm_exposure";
    private static final String ST_INFO_DPM_CLICK = "st_info_dpm_click";
    private static final String TITLE = "title";
    private static final String BODY_HTML = "bodyHtml";
    private static final String ISPRIZERECOMMEND = "isPrizeRecommend";

    @Autowired
    private GuidePageService guidePageService;

    @Autowired
    private ActivityEngineService activityEngineService;

    @Autowired
    private ActivityService activityService;

    @Autowired
    private AdvertService advertService;

    @Autowired
    private SlotService slotService;

    @Autowired
    private UserBalanceService userBalanceService;

    @Autowired
    private ConsumerService consumerService;

    /** 直投页来源service */
    @Autowired
    private DirectPageSourceService directPageSourceService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    private Map<Integer,String> prizeAnnouncementMap;

    private List<String> prizes = Arrays.asList("京东10元优惠券","OPPO R11手机","优酷会员月卡","5元话费","七彩发光键鼠套装","爱奇艺VIP8.5折",
            "饿了么4-15元优惠券","10元话费");

    @Override
    public ModelAndView index(HttpServletRequest request, IndexReq req, UserAccount consumer) throws ActivityException {
        GuidePageDto dto = guidePageService.getGuidePage(req.getId());
        GuidePageSkinDto skin = guidePageService.getGuidePageSkin(dto.getSkinId());
        Integer isPrizeRecommend = 1;
        Long slotId = req.getSlotId();
        if (!"preview".equals(request.getParameter(Constants.LOGIN))) {
            Optional<SlotDto> optional = slotService.getSlot(slotId);
            if (optional.isPresent() && optional.get().getPlugBuoyConfigDto() != null) {
                // 判空
                isPrizeRecommend = optional.get().getPlugBuoyConfigDto().getIsPrizeRecommend();
            }
        }
        //静态域名切换
        skin.setHtml(DomainUtil.replaceDomain(skin.getHtml(), DomainUtil.getCurrentYunDomain(request)));

        ModelAndView model;
        Integer pageType = dto.getPageType();
        directPageSourceService.log(consumer.getUserId());
        if (PageType.MAINMEET.equalsCode(pageType)) {
            model = new ModelAndView("mainmeet/index");
            model.addObject("id", dto.getId());
            model.addObject(BODY_HTML, skin.getHtml());
            model.addObject(TITLE, dto.getTitle());
            model.addObject(ISPRIZERECOMMEND, Integer.valueOf(1).equals(isPrizeRecommend));
            //设置dsm
            if (StringUtils.isNotBlank(req.getDsm())) {
                req.setDsm(DsmInfo.getDsmFromDsm(req.getDsm(), Constants.DSM.DSM_C_5, req.getId()));
            }
            buildActUrl(model, dto, dto.getActivitys(), request, req, consumer);
        } else if (PageType.ACTCENTER.equalsCode(pageType)) {
            model = new ModelAndView("actcenter/index");
            model.addObject("id", dto.getId());
            model.addObject(TITLE, dto.getTitle());
            model.addObject(BODY_HTML, skin.getHtml());
            model.addObject("dpm", request.getParameter("dpm"));
            model.addObject("login", request.getParameter(Constants.LOGIN));
            model.addObject("slotId", request.getParameter(Constants.SLOTID));
            model.addObject("deviceId", request.getParameter(Constants.DEVICE_ID));
            model.addObject("appKey", request.getParameter(Constants.APP_KEY));
            model.addObject(ISPRIZERECOMMEND, Integer.valueOf(1).equals(isPrizeRecommend));
        } else {
            if (dto.getExtInfo() != null && Objects.equals(dto.getExtInfo().getDirectType(), BalanceType.GAME.getType())) {
                model = new ModelAndView("directPage/game");
                setUserInfo(request, req, consumer, dto, slotId, model);
            } else {
                model = new ModelAndView("directPage/index");
            }
            model.addObject("id", dto.getId());
            model.addObject("centerId", "");
            model.addObject(TITLE, dto.getTitle());
            model.addObject(BODY_HTML, skin.getHtml());
            model.addObject("dpm", request.getParameter("dpm"));
            model.addObject("login", request.getParameter(Constants.LOGIN));
            model.addObject("slotId", request.getParameter(Constants.SLOTID));
            model.addObject("deviceId", request.getParameter(Constants.DEVICE_ID));
            model.addObject("appKey", request.getParameter(Constants.APP_KEY));
            model.addObject(ISPRIZERECOMMEND, Integer.valueOf(1).equals(isPrizeRecommend));
            // 默认true
            model.addObject("isPhone", true);
            /**
             * 经过直投页时的链路数据获取
             * @see http://cf.dui88.com/pages/viewpage.action?pageId=7683525
             * @modify lichao 2018-3-25
             */
            //过直投页时，如果没有缓存过key,则直接缓存key,之后的逻辑
            directPageSourceService.put(consumer.getUserId(), dto.getId());
        }

        model.addObject(Constants.VALUENAME.CONSUMER_ID, consumer.getUserId());
        model.addObject("host", DomainUtil.getHost(request));
        model.addObject("pageHost", "//" + request.getHeader("host"));
        return model;
    }

    private void setUserInfo(HttpServletRequest request, IndexReq req, UserAccount consumer, GuidePageDto dto, Long slotId, ModelAndView model) throws ActivityException {
        if (!"preview".equals(request.getParameter(Constants.LOGIN))) {
            directSpecialSet(model, dto, slotId, consumer, request);
            Long amount = userBalanceService.getAmount(consumer.getUserId(), BalanceType.GAME.getType());
            model.addObject("amount", ObjectUtils.defaultIfNull(amount,0L));
            String host = request.getHeader("host");
            JSONObject jsonObject = buildNewGameHallEmbed(req.getDsm(),consumer.getAppId(),consumer.getUserId()
                    ,host,dto
                    .getId());
            model.addObject("embed",jsonObject.toJSONString());
        } else {
            //返回给前端用户信息
            model.addObject("sex", 0);
            model.addObject("headUrl", "");
            model.addObject("nickName", "预览用户");
            model.addObject("firstLogin", 0);
            model.addObject("rewardAmount", 0);
            model.addObject("amount", 0);
            model.addObject("embed", "0");
        }
    }

    public static void main(String[] args) {
        System.out.println(JSONObject.toJSONString(""));
    }

    private void directSpecialSet(ModelAndView model, GuidePageDto dto, Long slotId, UserAccount userAccount, HttpServletRequest request) throws ActivityException {
        //1.设置手机登录字段
        Optional<SlotDto> optional = slotService.getSlot(slotId);
        Long userId = userAccount.getUserId();
        if (!optional.isPresent() || optional.get().getPlugBuoyConfigDto() == null) {
            return;
        }
        model.addObject("isPhone", optional.get().getPlugBuoyConfigDto().getLoginType().equals(SlotLoginType.PHONE.getType()));

        if(!RequestLocal.get().getLoginStatus() && null != dto.getExtInfo() && BalanceType.GAME.getType().equals(dto.getExtInfo().getDirectType())){
            //从其余渠道（返回，浮标等非登录场景）进入游戏大厅的时候，需要特殊处理
            ConsumerDto consumerDto = new ConsumerDto(userAccount.getAppId(), userAccount.getPartnerUserId());
            consumerDto.setLogin(SlotLoginType.NORMAL);
            Random random = new Random();
            consumerDto.getExtInfo().setImg("//yun.duiba.com.cn/h5-mami/webgame/web-login/header/newhander" + (random.nextInt(4) + 1) + ".png");
            consumerDto.getExtInfo().setNickName(consumerService.getVisitorNickName(6, 0));
            consumerDto.getExtInfo().setSex(0);
            ConsumerDto consumer = consumerService.getOrCreateConsumer(consumerDto);
            userId = consumer.getUserId();
            ConsumerCache consumerCache = consumerDto.toConsumerCache();
            consumerCache.setDeviceId(consumerDto.getDeviceId());
            consumerCache.setUserId(userId);
            consumerService.confirmNickName(consumerCache.getNickName());
            consumerService.setConsumerCache(consumerCache);
            userAccount.setUserId(userId);
            userAccount.setLoginStatus(true);
            RequestLocal.get().setCookie(userAccount);
        }

        //4.1首次登陆发奖
        BalanceRecordAdd add = null;

        //用户非首次登录，没有奖励逻辑
        if (RequestLocal.get().getLoginStatus() && null != dto.getExtInfo() && BalanceType.GAME.getType().equals(dto.getExtInfo().getDirectType())) {
            Long dailyGive = dto.getExtInfo().getDailyGive();
            Long firstGive = dto.getExtInfo().getFirstGive();
            if (firstGive != null && 0 != firstGive && consumerService.isFirstGive(userId, BalanceType.GAME)) {
                add = new BalanceRecordAdd();
                add.setBalanceType(BalanceType.GAME);
                add.setAmount(firstGive);
                add.setRecordType(BalanceRecordType.FIRST_LOGIN);
                model.addObject("firstLogin", 1);
                model.addObject("rewardAmount", firstGive);
                consumerService.setTodayFirstGive(userId.toString(), firstGive);//首次赠送完成后，当日不再赠送每日首次

            } else if (null != dailyGive && 0 != dailyGive && !consumerService.isTodayFirstGive(userId.toString())) {
                //用户媒体首次登录，
                add = new BalanceRecordAdd();
                add.setBalanceType(BalanceType.GAME);
                add.setAmount(dailyGive);
                add.setRecordType(BalanceRecordType.GAME_DAILY_FIRST);
                model.addObject("firstLogin", 2);
                model.addObject("rewardAmount", add.getAmount());
                consumerService.setTodayFirstGive(userId.toString(), add.getAmount());
            } else {
                model.addObject("firstLogin", 0);
                model.addObject("rewardAmount", 0);
            }
        }

        //返回给前端用户信息
        ConsumerCache consumerCache = consumerService.getConsumerCache(userId);
        if (null != consumerCache) {
            model.addObject("sex", consumerCache.getSex());
            model.addObject("headUrl", consumerCache.getImg());
            model.addObject("nickName", consumerCache.getNickName());
        }

        if(null != add){
            add.setAppId(userAccount.getAppId());
            add.setPageId(dto.getId());
            add.setUserId(userId);
            add.setSlotId(slotId);
            userBalanceService.addAmount(add);
        }
    }

    private Queue<ActivityForActCenterVO> getActCenterActivityForDirect(DirectPageReq req, Integer num) throws ActivityException {
        List<RspActivityCenterDto> engineRsp = activityEngineService.getActCenterList(req.getSlotId());
        List<TuiaActivityDto> lists = activityService.getBatchActivitys(getIds(engineRsp));
        List<ActivityForActCenterVO> actList = BeanUtils.copyList(filterActivity(lists, engineRsp, req.getConsumerId(), num, req.getSlotId()),
                ActivityForActCenterVO.class);

        return Queues.newLinkedBlockingQueue(actList);
    }

    @Override
    public GetActivitysRsp getActivity4ActCenter(IndexReq indexReq, Integer num, HttpServletRequest request)
            throws ActivityException {
        GetActivitysRsp rsp = new GetActivitysRsp();
        Long consumerId = RequestLocal.get().getCid();
        Long appId = RequestLocal.get().getAppId();
        GuidePageDto guidePageDto = guidePageService.getGuidePage(indexReq.getId());
        int pageType = guidePageDto.getPageType();
        List<RspActivityCenterDto> engineRsp = activityEngineService.getActCenterList(Long.valueOf(request.getParameter(Constants.SLOTID)));
        List<TuiaActivityDto> lists = activityService.getBatchActivitys(getIds(engineRsp));
        List<ActivityForActCenterVO> actList = BeanUtils.copyList(filterActivity(lists, engineRsp, consumerId, num, indexReq.getSlotId()), ActivityForActCenterVO.class);

        String dsm = indexReq.getDsm();
        if (StringUtils.isNotBlank(dsm)) {
            indexReq.setDsm(DsmInfo.getDsmFromDsm(dsm, PathUtil.pageTypeToDSMc(pageType), indexReq.getId()));
        }
        if ((PageType.DIRECT.getCode()).equals(pageType)) {
            Long directPage = this.directPageSourceService.get(consumerId);
            //dpm  默认dpm
            String dpm = DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_48, Constants.DPM.DPM_DEFAULT, Constants.DPM.DPM_DEFAULT);
            int index = 1;
            for (ActivityForActCenterVO actVo : actList) {
                Map<String, String> map = new HashMap<>();
                //获取dpm c位 和 d位
                Integer[] dpmCD = getDirectPageDpmcAndDpmd(indexReq.getPosition(), index);
                String dcm = DpmInfo.dcmInfo(Constants.DCM.DCM_A_701, actVo.getId(), Constants.DCM.DCM_C_3, indexReq.getId());
                //设置dpm
                if (dpmCD != null && dpmCD.length != 0) {
                    dpm = DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_48, dpmCD[0], dpmCD[1]);
                }
                indexReq.setDpm(dpm);
                // 将对应的活动的埋点信息添加
                buildAdvertRspForEmbed(map, appId, guidePageDto.getId(), consumerId,
                        "//" + request.getHeader("host"), dpm, dcm, dsm,directPage);
                indexReq.setDcm(dcm);
                actVo.setEmbedInfo(map);
                actVo.setUrl(PathUtil.getActivityUrl(actVo.getId(), indexReq, indexReq.getId(), pageType));
                index++;
            }

        } else {
            for (ActivityForActCenterVO actVo : actList) {
                actVo.setUrl(PathUtil.getActivityUrl(actVo.getId(), indexReq, indexReq.getId(), pageType));
            }
        }

        rsp.setList(actList);

        //图片域名切换
        rsp.replaceDomain(DomainUtil.getCurrentYunDomain(request));
        return rsp;
    }

    private List<TuiaActivityDto> filterActivity(List<TuiaActivityDto> lists, List<RspActivityCenterDto> rsps, Long consumerId, Integer num, Long slotId) {

        List<String> slotTag = this.slotService.getSlotIdTags(slotId);
        List<Long> activityIds = EntityUtil.getParam(lists, TuiaActivityDto::getId);
        Map<Long, Set<Long>> tags = this.activityService.getActivitysTags(activityIds);

        lists = lists.stream().filter(activity -> (!CollectionTool.containsStringAny(tags.get(activity.getId()), slotTag))).collect(Collectors.toList());

        List<TuiaActivityDto> actList = new ArrayList<>();
        if (CollectionUtils.isEmpty(rsps)) {
            return actList;
        }

        List<Long> topIds = new LinkedList<>();
        List<Long> otherIds = new LinkedList<>();
        processIdList(rsps, consumerId, topIds, otherIds);
        //如果过滤完的活动不够列表展示需要的num,则放开过滤条件,重新挑出置顶活动
        if (num > topIds.size() + otherIds.size()) {
            topIds = new LinkedList<>();
            otherIds = new LinkedList<>();
            for (RspActivityCenterDto act : rsps) {
                if (1 == act.getIsTop()) {
                    topIds.add(act.getActivityId());
                } else if (0 == act.getIsTop()) {
                    otherIds.add(act.getActivityId());
                }
            }
        }
        Collections.shuffle(otherIds);
        topIds.addAll(otherIds);
        //根据排序之后的活动id列表,从查询结果中找到活动dto,如果没有则丢弃
        actList = ActivityUtil.sortActivityList(lists, topIds);
        //只返回需要的数量,不够就全部返回
        if (actList.size() <= num) {
            return actList;
        }

        return actList.subList(0, num);
    }

    private void processIdList(List<RspActivityCenterDto> rsps, Long consumerId, List<Long> topIds, List<Long> otherIds) {
        Map<Object, Object> consumerActivityDojoinCacheMap = activityService.getConsumerActivityDojoinCacheMap(consumerId);
        for (RspActivityCenterDto act : rsps) {
            //获取该用户改活动参与次数,0表示未参加过,-1表示当日已抽完
            Object timeStr = consumerActivityDojoinCacheMap.get(act.getActivityId().toString());
            int times = null == timeStr ? 0 : Integer.valueOf(timeStr.toString());
            //挑选出置顶的未参与过的活动
            if (0 == times && 1 == act.getIsTop()) {
                topIds.add(act.getActivityId());
            } else if (0 == times && 0 == act.getIsTop()) {
                //挑选未置顶未参与过活动
                otherIds.add(act.getActivityId());
            }
        }
    }


    private List<Long> getIds(List<RspActivityCenterDto> rsps) {
        List<Long> ids = new ArrayList<>();
        for (RspActivityCenterDto dto : rsps) {
            ids.add(dto.getActivityId());
        }
        return ids;
    }

    private void buildActUrl(ModelAndView model, GuidePageDto dto, List<GuidePageRelationDto> activitys, HttpServletRequest request, IndexReq req, UserAccount consumer) {
        if (null == activitys) {
            return;
        }
        List<String> mlist = new ArrayList<>();//活动url
        List<String> nlist = new ArrayList<>();//活动名称
        List<String> ulist = new ArrayList<>();//bannerUrl
        List<String> blockNames = new ArrayList<>();//区块名称

        // 告诉前端 该区块 是否有配置嵌入式插件
        List<Boolean> blist = new ArrayList<>();

        Map<String, BlockRsp> blocks = new LinkedHashMap<>();//区块数据
        BlockRelation blockRelation = new BlockRelation();

        for (GuidePageRelationDto activity : activitys) {
            BlockRsp rsp = blocks.get(activity.getBlockName());

            if (rsp == null) {
                rsp = new BlockRsp(activity);
                blocks.put(rsp.getBlockName(), rsp);
            }

            if (rsp.getActivityId() != null && IdType.ACTIVITY.getType().equals(activity.getIdType())) {
                rsp.setActivityName(activity.getActivityName());

                String url = PathUtil.getActivityUrl(activity.getActivityId(), req, dto.getId(), dto.getPageType());
                rsp.setUrl(url);
                mlist.add(url);

                nlist.add(activity.getActivityName());

                String bannerUrl = DomainUtil.replaceDomain(activity.getBannerUrl(), DomainUtil.getCurrentYunDomain(request));
                rsp.setBannerUrl(bannerUrl);
                ulist.add(bannerUrl);
            }
            if (IdType.PLUGIN.getType().equals(activity.getIdType())) {
                rsp.setHavePlugin(true);
                rsp.setPluginId(activity.getActivityId());
            }


            //配置区块关联数据
            setBlockRelatedData(activity, blockNames, blockRelation);
        }

        blocks.values().forEach(e -> {
            if (e.getPluginId() != null) {
                e.setHavePlugin(true);
                blist.add(true);
            } else {
                e.setHavePlugin(false);
                blist.add(false);
            }
        });
        model.addObject("mlist", JSONObject.toJSON(mlist));
        model.addObject("nlist", JSONObject.toJSON(nlist));
        model.addObject("ulist", JSONObject.toJSON(ulist));
        model.addObject("blist", JSONObject.toJSON(blist));

        //每个区块构建埋点信息
        setMainMeetEmbed(model, blockNames, blockRelation, dto, consumer, request, blocks);

        model.addObject("blocks", JSONObject.toJSON(blocks.values()));
        //埋点信息构建参数（用于前端构建特殊埋点）
        model.addObject("app_id", consumer.getAppId());
        model.addObject("url", Constants.PATH.STATISTICS + Constants.PATH.CLICK);
        model.addObject("consumer_id", consumer.getUserId());
        model.addObject("domain", DomainConstantUtil.getAppEmbedClickUrl());// 埋点服务器Domain
        model.addObject("domainWeb", "//" + request.getHeader("host"));
    }

    /**
     * 配置区块关联数据
     *
     * @param activity
     * @param blockNames
     * @param blockRelation
     * @return
     */
    private void setBlockRelatedData(GuidePageRelationDto activity, List<String> blockNames, BlockRelation blockRelation) {
        String blockName = activity.getBlockName();

        Integer idType = activity.getIdType();


        if (null != blockName) {
            if (idType == null || idType == 1) {//活动
                blockNames.add(blockName);
                blockRelation.getRelationActivityId().put(blockName, activity.getActivityId());
            } else {
                blockRelation.getIsIncludeMap().put(blockName, true);
                if (!blockRelation.getRelationPluginId().containsKey(blockName)) {
                    blockRelation.getRelationPluginId().put(blockName, activity.getActivityId());
                }
                return;
            }
        } else {//保证blist 与其他list 对应
            blockRelation.getIsIncludeMap().put(activity.getId() + "temp", false);
        }
    }

    /**
     * 主会场每个区块构建埋点信息
     *
     * @param model         ModelAndView
     * @param blockNames    区块名列表
     * @param blockRelation 区块关联数据
     * @param dto           引导页
     * @param consumer      用户信息
     * @param request       HttpServletRequest
     * @return
     */
    private void setMainMeetEmbed(ModelAndView model, List<String> blockNames, BlockRelation blockRelation, GuidePageDto dto, UserAccount consumer, HttpServletRequest request, Map<String, BlockRsp> blocks) {
        //曝光埋点列表
        List<String> stInfolist = new ArrayList<>();
        //点击埋点列表
        List<String> stClickList = new ArrayList<>();
        Long directPage = this.directPageSourceService.get(consumer.getUserId());
        for (int place = 0; place < blockNames.size(); ++place) {
            String dpm = DpmInfo.getDpmInfo(consumer.getAppId(), Constants.DPM.DPM_B_57, dto.getId().intValue(), place + 1);

            String blockName = blockNames.get(place);
            Boolean rs = blockRelation.getIsIncludeMap().get(blockName);
            BlockRsp block = blocks.get(blockName);
            if (block == null) {
                block = new BlockRsp();//防null报错
            }

            if (rs == null ? false : rs) {
                Long pluginId = blockRelation.getRelationPluginId().get(blockNames.get(place));
                String dcm = pluginId == 0 ? "" : DpmInfo.dcmInfo(Constants.DCM.DCM_A_702, blockRelation.getRelationPluginId().get(blockNames.get(place)), Constants.DCM.DCM_C_1, dto.getId());

                block.setStExposure(DpmInfo.setStPluginInfo(consumer.getAppId(), consumer.getUserId(), dpm, dcm, "//" + request.getHeader("host"),directPage));
                stInfolist.add(block.getStExposure());

                block.setStClick(DpmInfo.setStPluginClick(consumer.getAppId(), consumer.getUserId(), "//" + request.getHeader("host"), dpm, dcm,directPage));
                stClickList.add(block.getStClick());

            } else {
                Long activityId = blockRelation.getRelationActivityId().get(blockNames.get(place));
                String dcm = activityId == 0 ? "" : DpmInfo.dcmInfo(Constants.DCM.DCM_A_701, blockRelation.getRelationActivityId().get(blockNames.get(place)), Constants.DCM.DCM_C_1, dto.getId());

                block.setStExposure(DpmInfo.setStActivityInfo(consumer.getAppId(), consumer.getUserId(), dpm, dcm, "//" + request.getHeader("host"),directPage));
                stInfolist.add(block.getStExposure());

                block.setStClick(DpmInfo.setStActivityClick(consumer.getAppId(), consumer.getUserId(), dpm, dcm, "//" + request.getHeader("host"),directPage));
                stClickList.add(block.getStClick());
            }
        }
        model.addObject("st_exposure_list", JSONObject.toJSON(stInfolist));
        model.addObject("st_click_list", JSONObject.toJSON(stClickList));
    }


    @Override
    public JSONObject getAdvertCounts(HttpServletRequest request) throws ActivityException {
        JSONObject jsonObject = new JSONObject();
        String location = request.getParameter("location");
        if (null != location && "weidai".equals(location)) {
            jsonObject.put("status", activityService.getAdvertTimes(location) <= 12000 ? Boolean.TRUE : Boolean.FALSE);
        } else {
            jsonObject.put("status", Boolean.FALSE);
        }

        return jsonObject;
    }

    /**
     * 设置浮标id，dsm
     *
     * @param req req
     */
    private void setBuoyIdAndSetDsm(DirectPageReq req) {
        Long buoyId = null;
        String dsm = req.getDsm();
        if (StringUtils.isNotBlank(dsm)) {
            String dsmA = DsmInfo.getParamFromDsm(dsm, 1);
            String dsmB = DsmInfo.getParamFromDsm(dsm, 2);
            dsm = DsmInfo.dsmInfo(Integer.parseInt(dsmA), Integer.parseInt(dsmB), Constants.DSM.DSM_C_3, req.getPageId());
            req.setDsm(dsm);
            int preSource = Integer.parseInt(DsmInfo.getParamFromDsm(dsm, 1));
            if (preSource == (PreSource.BUOY.getType())) {
                buoyId = Long.parseLong(DsmInfo.getParamFromDsm(dsm, 2));
            }

        }
        if (StringUtils.isBlank(dsm)) {
            dsm = Constants.DSM.DSM_UNKNOWN;
        }
        req.setDsm(dsm);
        req.setBuoyId(buoyId);
    }

    @Override
    public DirectPageRsp getAdvert(HttpServletRequest request, DirectPageReq req) throws ActivityException {

        DirectPageRsp rsp = new DirectPageRsp();
        List<Long> advertIds = Lists.newArrayList();
        List<AdvertVO> list = req.getAdverts();

        //设置浮标id，dsm
        this.setBuoyIdAndSetDsm(req);

        //广告map
        Map<Long, AdvertVO> advertVOMap = new HashMap<>();
        //链接list
        List<AdvertVO> staticAdvertVOs = Lists.newArrayList();
        for (AdvertVO advertVo : list) {
            if (advertVo.getId() != null) {
                advertVOMap.put(advertVo.getId(), advertVo);
                advertIds.add(advertVo.getId());
            } else {
                staticAdvertVOs.add(advertVo);
            }
        }

        if (CollectionUtils.isNotEmpty(list)) {

            // 查询有效的广告
            List<AdvertDirectDto> advertDtos = this.advertService.getValidAdverts(req, advertIds);
            Long directPage = this.directPageSourceService.get(req.getConsumerId());
            // 遍历广告
            List<AdvertVO> adverts = advertForEach(advertVOMap, advertDtos, req,directPage);
            //没有advertId的集合添加埋点数据
            adverts.addAll(urlForEach(staticAdvertVOs, req,directPage));
            rsp.setAdverts(adverts);
        }
        return rsp;
    }

    @Override
    public DirectBlockRsp getDirectBlock(HttpServletRequest request, DirectPageReq req, boolean limitTimes) throws ActivityException {

        DirectBlockRsp rsp = new DirectBlockRsp(req.getPageId());
        Set<Long> advertIds = Sets.newHashSet();

        //设置dsm
        String dsm = DsmBuilder.directBlockBuild(req.getDsm(), req.getPageId());
        req.setDsm(dsm);

        List<GuidePageBlockDto> dtos = this.guidePageService.getDirectBlocks(req.getPageId());

        if (CollectionUtils.isEmpty(dtos)) {
            return rsp;
        }

        int num = 0;

        //统计活动区块数量,广告id
        for (GuidePageBlockDto dto : dtos) {
            if (DirectBlockType.ACTIVITY_BLOCK.getType().equals(dto.getBlockType())) {
                num++;
            } else if (DirectBlockType.ADVERT_BLOCK.getType().equals(dto.getBlockType())) {
                advertIds.addAll(dto.getListAdvertIds());
            }

        }

        //查询广告
        List<AdvertDirectDto> advertDtos;
        if (limitTimes) {
            advertDtos = this.advertService.getValidAdverts(Lists.newArrayList(advertIds));
        } else {
            advertDtos = this.advertService.getValidAdverts(req, Lists.newArrayList(advertIds));
        }

        Map<Long, AdvertDirectDto> advertMap = EntityUtil.transf(advertDtos, AdvertDirectDto::getAdvertId);

        //查询活动
        Queue<ActivityForActCenterVO> activityQueue = this.getActCenterActivityForDirect(req, num);

        String landUrl = activityService.getLandUrlByAppId(req.getAppId());
        Long directPage = this.directPageSourceService.get(req.getConsumerId());
        for (GuidePageBlockDto dto : dtos) {
            rsp.addBlock(createBlock(dto, advertMap, activityQueue,
                    LoginType.PREVIEW.equalsCode(req.getLogin()), landUrl),
                    dto.getRegionName(), dto.getRegionType(), req, DomainUtil.getCurrentYunDomain(request), directPage, false);
        }

        return rsp;
    }

    @Override
    public DirectBlockRsp getDirectBlockNew(HttpServletRequest request, DirectPageReq req) throws ActivityException {
        DirectBlockRsp rsp = new DirectBlockRsp(req.getPageId());
        Set<Long> advertIds = Sets.newHashSet();  //广告ids
        Set<Long> activityIds = Sets.newHashSet();//活动ids
        Set<Long> pageIds = Sets.newHashSet();    //主会场ids

        //设置dsm
        String dsm = DsmBuilder.directBlockBuild(req.getDsm(), req.getPageId());
        req.setDsm(dsm);

        // 查询直投页区块
        List<GuidePageBlockDto> dtos = this.guidePageService.getDirectBlocks(req.getPageId());
        if (CollectionUtils.isEmpty(dtos)) {
            return rsp;
        }
        List<GuidePageBlockDto> allDtos = getGuidePageBlockDtos(req, advertIds, activityIds, pageIds, dtos);


        // 查询广告位标签
        List<String> slotTag = this.slotService.getSlotIdTags(req.getSlotId());

        Map<Long, AdvertDirectDto> advertMap = getAdvertMap(Lists.newArrayList(advertIds), req, false);
        Map<Long, TuiaActivityDto> activityMap = getActivityMap(Lists.newArrayList(activityIds), slotTag);
        Map<Long, GuidePageDto> guidePageMap = getGuidePageMap(Lists.newArrayList(pageIds), slotTag);
        String landUrl = activityService.getLandUrlByAppId(req.getAppId());
        Long directPage = this.directPageSourceService.get(req.getConsumerId());

        // 区块定制需求 根据特定广告决定区块非否展示。。。判断区块是否可展示
        boolean custom = !advertMap.containsKey(27967L) && !advertMap.containsKey(27809L);

        for (GuidePageBlockDto dto : allDtos) {
            rsp.addBlock(createBlock(dto, advertMap, activityMap, guidePageMap, landUrl)
                    , dto.getRegionName(), dto.getRegionType(), req, DomainUtil.getCurrentYunDomain(request), directPage, custom);
        }
        return rsp;
    }

    @NotNull
    private List<GuidePageBlockDto> getGuidePageBlockDtos(DirectPageReq req, Set<Long> advertIds, Set<Long> activityIds, Set<Long> pageIds, List<GuidePageBlockDto> dtos) {
        //捞id
        List<GuidePageBlockDto> allDtos = Lists.newArrayList();
        List<GuidePageBlockDto> temp = Lists.newArrayList();
        for (GuidePageBlockDto dto : dtos) {
            if (DirectBlockType.ADVERT_BLOCK2.getType().equals(dto.getBlockType())) {
                advertIds.addAll(dto.getListAdvertIds());
                if (IdType.ACTIVITY.getType().equals(dto.getIdType())) {
                    activityIds.addAll(dto.getListRelationIds());
                } else if (IdType.GUIDEPAGE.getType().equals(dto.getIdType())) {
                    pageIds.addAll(dto.getListRelationIds());
                }
            } else if (DirectBlockType.ACTIVITY_BLOCK2.getType().equals(dto.getBlockType())) {
                activityIds.addAll(dto.getListRelationIds());
            } else if (DirectBlockType.MAINMEET_BLOCK.getType().equals(dto.getBlockType())) {
                pageIds.addAll(dto.getListRelationIds());
            }

            temp = dealGameBlockDtos(req, allDtos, temp, dto);
        }

        // 区块定制需求 根据特定广告决定区块非否展示。。。前置查询
        if (Long.valueOf(961L).equals(req.getPageId())) {
            advertIds.add(27967L);
            advertIds.add(27809L);
        }
        return allDtos;
    }

    @NotNull
    private List<GuidePageBlockDto> dealGameBlockDtos(DirectPageReq req, List<GuidePageBlockDto> allDtos, List<GuidePageBlockDto> temp, GuidePageBlockDto dto) {
        if (DirectBlockType.GAME_BLOCK.getType().equals(dto.getBlockType())) {
            //对游戏区块单独处理，支持单个区块种配置的游戏列表
            //如果是连续的游戏区块，判断是否同temp中的区块名相同，相同放入temp，如果不同，清空temp，重新放入
            if (temp.size() == 0 || temp.get(0).getBlockName().equals(dto.getBlockName())) {
                //1.如果是连续中的第一个，则放入temp || 如果是连续的游戏区块，判断是否同temp中的区块名相同，相同放入temp
                temp.add(dto);
            } else {
                //如果区块名称不同，则清空temp
                temp = clearTempList(allDtos, temp, req.getConsumerId());
                temp.add(dto);
            }
        } else {
            //非游戏区块目前还不支持区块列表，直接放入
            allDtos.add(dto);
            temp = clearTempList(allDtos, temp, req.getConsumerId());
        }
        return temp;
    }

    private List<GuidePageBlockDto> clearTempList(List<GuidePageBlockDto> allDtos, List<GuidePageBlockDto> temp, Long userId){
        //清空游戏区块列表时，将随机之后的区块替换掉原有列表
        if(temp.size() >= 1){
            GuidePageBlockDto dto = randomGameBlockByUserId(temp, userId);
            allDtos.add(dto);
        }
        //然后重新返回一个新的空list
        return Lists.newArrayList();
    }

    private static GuidePageBlockDto randomGameBlockByUserId(List<GuidePageBlockDto> dtos, Long userId){
        if(dtos.size() == 1){
            return dtos.get(0);
        }
        //根据用户id随机一个种子数，来保证该用户在同一个列表中每次取到的都是同一个值，更换列表之后则重新随机
        //中奖的随机数,目前为int类型 对于概率而言只支持1/10000的精度
        Random seed = new Random(userId);
        double point = Double.valueOf(seed.nextInt(10000) + 1) / 100.00;
        System.out.println("" + point);
        double temp = 0.0;
        for(GuidePageBlockDto dto : dtos){
            temp += Double.valueOf(dto.getExtInfo().getFlowRatio());
            if(point <= temp){
                return dto;
            }
        }
        return dtos.get(seed.nextInt(dtos.size()));
    }

    @Override
    public String getActCenterUrl(HttpServletRequest request, IndexReq req) throws ActivityException {
        Long appId = RequestLocal.get().getAppId();
        req.setDpm(DpmBuilder.returnPageBuild(appId));//dpm
        req.setDsm(DsmBuilder.returnToActCenterBuild(req.getId(), request.getHeader(Constants.HTTPHEADER.REFERER)));
        return PathUtil.getGuidePageUrl(guidePageService.getActCenterId(), req, PageType.ACTCENTER.getCode());
    }

    private Block createBlock(GuidePageBlockDto dto, Map<Long, AdvertDirectDto> advertMap,
                              Map<Long, TuiaActivityDto> activityMap, Map<Long, GuidePageDto> guidePageMap,
                              String landUrl) {
        Block block = null;

        if (DirectBlockType.ADVERT_BLOCK2.getType().equals(dto.getBlockType())) {
            block = getAdvertBlock2(dto, advertMap, activityMap, guidePageMap);
        } else if (DirectBlockType.ACTIVITY_BLOCK2.getType().equals(dto.getBlockType())) {
            block = getActivityBlock(dto, activityMap);
        } else if (DirectBlockType.MAINMEET_BLOCK.getType().equals(dto.getBlockType())) {
            block = getGuidePageBlock(dto, guidePageMap);
        } else if (DirectBlockType.GAME_BLOCK.getType().equals(dto.getBlockType())) {
            block = new GameBlock(dto);
        } else if (DirectBlockType.PLUGIN_BLOCK.getType().equals(dto.getBlockType())) {
            block = getEmbeddedPluginBlock(dto, block);
        }
        if (block != null && StringUtils.isNotBlank(block.getUrl()) && StringUtils.isNotBlank(landUrl)) {
            block.setUrl(replaceLandDomain(block.getUrl(), landUrl));
        }
        return block;
    }

    private Block getEmbeddedPluginBlock(GuidePageBlockDto dto, Block block) {
        Long pluginId = getFirst(dto.getListRelationIds());
        if (pluginId != null) {
            block = new EmbeddedPluginBlock(dto, pluginId);
        }
        return block;
    }

    private Block getActivityBlock(GuidePageBlockDto dto, Map<Long, TuiaActivityDto> activityMap) {
        Long activityId = getFirst(dto.getListRelationIds());
        if (activityId != null && activityMap.containsKey(activityId)) {
            return new ActivityBlock(dto, activityId);
        }
        return null;
    }

    private Block getGuidePageBlock(GuidePageBlockDto dto, Map<Long, GuidePageDto> guidePageMap) {
        Block block = null;
        Long pageId = getFirst(dto.getListRelationIds());
        if (pageId != null && guidePageMap.containsKey(pageId)) {
            GuidePageDto guidePageDto = guidePageMap.get(pageId);
            if (PageType.MAINMEET.equalsCode(guidePageDto.getPageType())) {
                block = new MainMeetBlock(dto, pageId);
            } else {
                block = new DirectBlock(dto, pageId);
            }
        }
        return block;
    }

    /**
     * 有个定制需求,特定的页面id,第一个区块,如果特定的2个广告id不可用,该区块不展示
     * 该定制需求 下掉的时候，可改回调用上面的方法
     *
     * @param dto
     * @param guidePageMap
     * @param advertMap
     * @return
     */
    private Block getCustomGuidePageBlock(GuidePageBlockDto dto, Map<Long, GuidePageDto> guidePageMap, Map<Long, AdvertDirectDto> advertMap, int index,Long pageId) {
        if (Long.valueOf(961).equals(pageId) && 0 == index && !advertMap.containsKey(27967L) && !advertMap.containsKey(27809L)) {
            return null;
        }

        return getGuidePageBlock(dto, guidePageMap);
    }

    /**
     * 构建嵌入式插件区块
     *
     * @param dto
     * @param embeddedPluginMap
     * @param block
     * @return
     */
    private Block getEmbeddedPluginBlock(GuidePageBlockDto dto, Map<Long, ActivityPluginDto> embeddedPluginMap, Block block) {
        Long embeddedPluginId = getRandom(dto.getListRelationIds());
        if (embeddedPluginId != null && embeddedPluginMap.containsKey(embeddedPluginId)) {
            block = new EmbeddedPluginBlock(dto, embeddedPluginId);
        }
        return block;
    }

    /**
     * 构建广告区块
     * 实际生成的可能不是广告
     *
     * @param dto
     * @param advertMap
     * @return 广告区块/url区块/活动区块/引导页区块
     */
    private Block getAdvertBlock2(GuidePageBlockDto dto, Map<Long, AdvertDirectDto> advertMap, Map<Long, TuiaActivityDto> activityMap, Map<Long, GuidePageDto> guidePageMap) {
        // 新需求，广告无效时，可降级为url/活动/引导页 区块
        Block block = null;
        Long advertId = getExistAdvertId(dto.getListAdvertIds(), advertMap);//获取有效广告id，若为null，跳转url
        if (advertId != null) {
            AdvertDirectDto advert = advertMap.get(advertId);
            block = new AdvertBlock(dto, advert.getPackageId()).setAdId(advertId)
            .setEffectiveMainType(advert.getLogExtMap()!=null?advert.getLogExtMap().get("effectiveMainType"):null);
            block.setUrl(advert.getPromoteURL());
        } else if (IdType.ACTIVITY.getType().equals(dto.getIdType())) {
            block = getActivityBlock(dto, activityMap);
        } else if (IdType.GUIDEPAGE.getType().equals(dto.getIdType())) {
            block = getGuidePageBlock(dto, guidePageMap);
        } else if (StringUtils.isNotBlank(dto.getUrl())) {
            block = new UrlBlock(dto);
        }
        return block;
    }

    /**
     * 落地页去除tuia的域名
     *
     * @param promoteUrl
     * @return
     */
    private String replaceLandDomain(String promoteUrl, String landUrl) {

        //1.如果不包含.tuia.cn 直接返回
        if (StringUtils.isEmpty(promoteUrl)) {
            return promoteUrl;
        }

        if (promoteUrl.contains(Constants.CUSTOM.TUIA_DOMAIN) || promoteUrl.contains(Constants.CUSTOM.TUIBAT_DOMAIN)) {
            if (StringUtils.isNotEmpty(landUrl)) {
                if (promoteUrl.contains(Constants.CUSTOM.TUIA_DOMAIN)) {
                    promoteUrl = promoteUrl.replace(Constants.CUSTOM.TUIA_DOMAIN, landUrl);
                } else {
                    promoteUrl = promoteUrl.replace(Constants.CUSTOM.TUIBAT_DOMAIN, landUrl);
                }
                promoteUrl = promoteUrl.replace("https:", "").replace("http:", "");
            }
        }

        return promoteUrl;
    }


    private Long getFirst(List<Long> ids) {
        if (CollectionUtils.isNotEmpty(ids)) {
            return ids.get(0);
        }
        return null;
    }

    private Long getRandom(List<Long> ids) {
        if (CollectionUtils.isNotEmpty(ids)) {
            return ids.get(RandomUtils.nextInt(ids.size()));
        }
        return null;
    }

    /**
     * 查询有效广告
     *
     * @param advertIds  广告列表
     * @param req        req
     * @param limitTimes 是否有广告次数限制逻辑
     * @return map
     * @throws ActivityException
     */
    private Map<Long, AdvertDirectDto> getAdvertMap(List<Long> advertIds, DirectPageReq req, boolean limitTimes)
            throws ActivityException {
        List<AdvertDirectDto> advertDtos;
        if (limitTimes) {
            advertDtos = this.advertService.getValidAdverts(advertIds);
        } else {
            advertDtos = this.advertService.getValidAdverts(req, advertIds);
        }

        return EntityUtil.transf(advertDtos, AdvertDirectDto::getAdvertId);
    }

    /**
     * 查询有效活动
     * <p>
     * 过滤逻辑：
     * 1.删除的活动
     * 2.关闭的活动
     * 3.命中广告位活动屏蔽标签的
     *
     * @param activityIds 活动ids
     * @return map
     */
    private Map<Long, TuiaActivityDto> getActivityMap(List<Long> activityIds, List<String> slotTag) throws ActivityException {

        Map<Long, TuiaActivityDto> map = Maps.newHashMap();
        List<TuiaActivityDto> optional = this.activityService.getBatchActivitys(activityIds);
        Map<Long,Set<Long>> tags = this.activityService.getActivitysTags(activityIds);//批量查询活动标签

        if (optional!=null&&!optional.isEmpty()) {
            optional.forEach(e -> {
                if (Boolean.FALSE.equals(e.getIsDeleted()) && Boolean.TRUE.equals(e.getIsOpen()) && !CollectionTool.containsStringAny(tags.get(e.getId()), slotTag)) {
                    map.put(e.getId(), e);
                }
            });
        }
        return map;
    }

    /**
     * 查询有效的主会场
     *
     * @param pageIds 主会场id
     * @return map
     */
    private Map<Long, GuidePageDto> getGuidePageMap(List<Long> pageIds, List<String> slotTag) {
        Map<Long, GuidePageDto> map = Maps.newHashMap();
        List<GuidePageDto> guides = this.guidePageService.getGuidePagesFromCache(pageIds);


        if (CollectionUtils.isNotEmpty(guides)) {
            // 查询主会场标签
            Map<Long, Set<Long>> mainMeetTags = this.guidePageService.getMainMeetActivityTag(pageIds);

            guides.forEach(e -> {
                if (Boolean.FALSE.equals(e.getIsDeleted()) && filterTags(slotTag, mainMeetTags, e.getId())) {
                    map.put(e.getId(), e);
                }
            });

        }

        return map;
    }

    private boolean filterTags(List<String> slotTag, Map<Long, Set<Long>> mainMeetTags, Long pageId) {
        if (CollectionUtils.isEmpty(slotTag) || mainMeetTags == null || mainMeetTags.isEmpty()) {
            return true;
        }

        Set<Long> tags = mainMeetTags.get(pageId);

        return CollectionUtils.isEmpty(tags) || !CollectionTool.containsStringAny(slotTag, tags);
    }


    /**
     * 创建区块
     *
     * @param dto           GuidePageBlockDto
     * @param advertMap     Map<Long(广告id),AdvertDirectDto>
     * @param activityQueue Queue<ActivityForActCenterVO> 活动中心的活动栈
     * @param preview       是否预览
     * @return Block
     */
    private Block createBlock(GuidePageBlockDto dto, Map<Long, AdvertDirectDto> advertMap, Queue<ActivityForActCenterVO> activityQueue, boolean preview, String landUrl) {
        Block block = null;

        if (DirectBlockType.ADVERT_BLOCK.getType().equals(dto.getBlockType())) {
            block = getBlock(dto, advertMap, preview, block);

        } else if (DirectBlockType.ACTIVITY_BLOCK.getType().equals(dto.getBlockType())) {
            if (!activityQueue.isEmpty()) {
                block = new ActivityBlock(dto, activityQueue.remove());
            }
        } else if (DirectBlockType.FREEDOM_BLOCK.getType().equals(dto.getBlockType())) {
            block = new UrlBlock(dto);
        }

        if (block != null && StringUtils.isNotBlank(block.getUrl()) && StringUtils.isNotBlank(landUrl)) {
            block.setUrl(replaceLandDomain(block.getUrl(), landUrl));
        }
        return block;
    }

    private Block getBlock(GuidePageBlockDto dto, Map<Long, AdvertDirectDto> advertMap, boolean preview, Block block) {
        Long advertId = getExistAdvertId(dto.getListAdvertIds(), advertMap);

        if (advertId != null || preview) {//预览时 展示区块
            AdvertDirectDto advert = advertMap.get(advertId);
            block = new AdvertBlock(dto, advert.getPackageId()).setAdId(advertId);
            block.setUrl(advert == null ? "" : advert.getPromoteURL());
        }
        return block;
    }

    private Long getExistAdvertId(List<Long> advertIds, Map<Long, AdvertDirectDto> advertMap) {
        Long advertId = null;

        if (CollectionUtils.isNotEmpty(advertIds)) {
            for (Long id : advertIds) {
                if (advertMap.containsKey(id)) {
                    advertId = id;
                    break;
                }
            }
        }
        return advertId;
    }

    /**
     * 遍历广告，配置埋点
     *
     * @param advertVOMap 广告map
     * @param advertDtos  广告引擎返回dto
     * @param req         请求
     * @return list
     */
    private List<AdvertVO> advertForEach(Map<Long, AdvertVO> advertVOMap, List<AdvertDirectDto> advertDtos, DirectPageReq req,Long directPage) {
        if (CollectionUtils.isNotEmpty(advertDtos)) {
            advertDtos.forEach(dto -> {
                Map<String, String> map = new HashMap<>();
                //2.拼接dcm
                String dcm = DpmInfo.dcmInfo(Constants.DCM.DCM_A_104, dto.getAdvertId(), Constants.DCM.DCM_C_3, req.getPageId());
                //3.拼接默认dpm
                String dpm = DpmInfo.getDpmInfo(req.getAppId(), Constants.DPM.DPM_B_48, Constants.DPM.DPM_DEFAULT, Constants.DPM.DPM_DEFAULT);
                //3.1获取advertVOMap中的对象
                AdvertVO advertVO = advertVOMap.get(dto.getAdvertId());
                if (StringUtils.isNotBlank(advertVO.getDpmC()) && StringUtils.isNotBlank(advertVO.getDpmD())) {
                    dpm = DpmInfo.getDpmInfo(req.getAppId(), Constants.DPM.DPM_B_48, Integer.parseInt(advertVO.getDpmC()), Integer.parseInt(advertVO.getDpmD()));
                }
                buildAdvertRspForEmbed(map, req.getAppId(), req.getPageId(), req.getAppId(), "//" + req.getHost(), dpm, dcm, req.getDsm(),directPage);

                Map<String, String> params = Maps.newHashMap();
                params.put(Constants.VALUENAME.ADVERT_ID, String.valueOf(dto.getAdvertId()));
                params.put(Constants.VALUENAME.SLOT_ID, String.valueOf(req.getSlotId()));
                params.put(Constants.VALUENAME.PAGE_ID, String.valueOf(req.getPageId()));
                params.put(Constants.KEY.DSM, req.getDsm());
                params.put(Constants.KEY.DCM, dcm);
                params.put(Constants.KEY.DPM, dpm);
                if(dto.getLogExtMap()!=null){
                    String effectiveMainType = dto.getLogExtMap().get("effectiveMainType");
                    if(StringUtils.isNotBlank(effectiveMainType)){
                        params.put("effectiveMainType", effectiveMainType);
                    }
                }

                AdvertVO vo = advertVOMap.get(dto.getAdvertId());
                if (vo != null) {
                    vo.setUrl(PathUtil.getDirectAdvert(req.getHost(), dto.getPromoteURL(), params));
                    vo.setEmbedInfo(map);
                }
            });
        }
        return Lists.newArrayList(advertVOMap.values());
    }

    private List<AdvertVO> urlForEach(List<AdvertVO> staticAdvertVOs, DirectPageReq req, Long directPage) {
        if (CollectionUtils.isNotEmpty(staticAdvertVOs)) {
            staticAdvertVOs.forEach(staticAdvertVO -> {
                Map<String, String> map = new HashMap<>();
                String dpm = DpmInfo.getDpmInfo(req.getAppId(), Constants.DPM.DPM_B_48, Constants.DPM.DPM_DEFAULT, Constants.DPM.DPM_DEFAULT);
                if (StringUtils.isNotBlank(staticAdvertVO.getDpmC()) && StringUtils.isNotBlank(staticAdvertVO.getDpmD())) {
                    dpm = DpmInfo.getDpmInfo(req.getAppId(), Constants.DPM.DPM_B_48, Integer.parseInt(staticAdvertVO.getDpmC()), Integer.parseInt(staticAdvertVO.getDpmD()));
                }

                buildAdvertRspForEmbed(map, req.getAppId(), req.getPageId(), req.getConsumerId(), "//" + req.getHost(), dpm, req.getDsm(),directPage);
                staticAdvertVO.setEmbedInfo(map);

                Map<String, String> params = Maps.newHashMap();
                params.put(Constants.VALUENAME.SLOT_ID, String.valueOf(req.getSlotId()));
                params.put(Constants.VALUENAME.PAGE_ID, String.valueOf(req.getPageId()));
                staticAdvertVO.setUrl(PathUtil.getDirectAdvert(req.getHost(), staticAdvertVO.getUrl(), params));
            });
        }
        return staticAdvertVOs;
    }


    @Override
    public void buildAdvertRspForEmbed(Map<String, String> map, Long appId, Long directPageId, Long consumerId, String host, String dsm) {
        String exposureDpm = DpmInfo.getDpmInfo(appId, Constants.DPM.DPM_B_48, Constants.DPM.DPM_DEFAULT, Constants.DPM.DPM_DEFAULT);
        String exposureDcm = DpmInfo.dcmInfo(Constants.DCM.DCM_A_104, Constants.DCM.DCM_DEFAULT, Constants.DCM.DCM_C_3, directPageId);
        JSONObject commonEmbedForDirectPage = DpmInfo.setCommonEmbedForDirectPage(appId, consumerId);
        map.put(ST_INFO_DPM_EXPOSURE, DpmInfo.setExposureEmbedForDirectPageLaunch(commonEmbedForDirectPage, host, exposureDcm, exposureDpm, dsm,null));
        map.put(ST_INFO_DPM_CLICK, DpmInfo.setClickInfoEmbedForDirectPage(commonEmbedForDirectPage, host, exposureDcm, exposureDpm, dsm,null));
    }


    @Override
    public void buildAdvertRspForEmbed(Map<String, String> map, Long appId, Long directPageId, Long consumerId,
                                       String host, String dpm, String dcm, String dsm, Long directPage) {
        JSONObject commonEmbedForDirectPage = DpmInfo.setCommonEmbedForDirectPage(appId, consumerId);
        map.put(ST_INFO_DPM_EXPOSURE, DpmInfo.setExposureEmbedForDirectPageLaunch(commonEmbedForDirectPage, host, dcm, dpm, dsm,directPage));
        map.put(ST_INFO_DPM_CLICK, DpmInfo.setClickInfoEmbedForDirectPage(commonEmbedForDirectPage, host, dcm, dpm, dsm,directPage));
    }

    @Override
    public void buildAdvertRspForEmbed(Map<String, String> map, Long appId, Long directPageId, Long consumerId, String host, String dpm, String dsm,Long directPage) {
        JSONObject commonEmbedForDirectPage = DpmInfo.setCommonEmbedForDirectPage(appId, consumerId);
        map.put(ST_INFO_DPM_EXPOSURE, DpmInfo.setExposureEmbedForDirectPage(commonEmbedForDirectPage, null, dpm, dsm,directPage));
        map.put(ST_INFO_DPM_CLICK, DpmInfo.setClickInfoEmbedForDirectPage(commonEmbedForDirectPage, host, dpm, dsm,directPage));
    }

    @Override
    public Integer[] getDirectPageDpmcAndDpmd(String position, int index) {
        if (position != null) {
            String[] s1 = StringUtils.split(position, ".");
            int counts = 0;
            for (int i = 0; i < s1.length; i++) {
                String[] s2 = StringUtils.split(s1[i], "-");
                int preCounts = counts;
                if (s2.length < 2) {
                    return new Integer[]{};
                }
                counts = Integer.parseInt(s2[1]) + counts;
                if (counts >= index) {
                    return new Integer[]{Integer.parseInt(s2[0]), index - preCounts};
                }
            }
        }
        return new Integer[]{};

    }

    @Override
    public Map<String, String> buildWalletEmbed(String dsm, Long appId, Long pageId, Long userId, String host) {
        Map<String, String> result = new HashMap<>();
        String dcm = DcmBuilder.directFixedBlockBuild(pageId);
        result.put("st_info_exposure_btn_record", new WalletEmbed(dcm, dsm, DpmBuilder.directBlockBuild(appId, Constants.DPM.DPM_C_0, Constants.DPM.DPM_D_2), userId, appId, host).buildExposure("st_info_exposure_btn_record"));//零钱明细按钮曝光
        result.put("st_info_click_btn_record", new WalletEmbed(dcm, dsm, DpmBuilder.directBlockBuild(appId, Constants.DPM.DPM_C_0, Constants.DPM.DPM_D_2), userId, appId, host).buildClick("st_info_click_btn_record"));//零钱明细按钮点击
        result.put("st_info_exposure_btn_login_wallet", new WalletEmbed(dcm, dsm, DpmBuilder.directBlockBuild(appId, Constants.DPM.DPM_C_0, Constants.DPM.DPM_D_1), userId, appId, host).buildExposure("st_info_exposure_btn_login_wallet"));//登陆钱包按钮曝光
        result.put("st_info_click_btn_login_wallet", new WalletEmbed(dcm, dsm, DpmBuilder.directBlockBuild(appId, Constants.DPM.DPM_C_0, Constants.DPM.DPM_D_1), userId, appId, host).buildClick("st_info_click_btn_login_wallet"));//登陆钱包按钮点击
        result.put("st_info_exposure_btn_alipay", new WalletEmbed(dcm, dsm, DpmBuilder.directBlockBuild(appId, Constants.DPM.DPM_C_0, Constants.DPM.DPM_D_3), userId, appId, host).buildExposure("st_info_exposure_btn_alipay"));//支付宝提现按钮曝光
        result.put("st_info_click_btn_alipay", new WalletEmbed(dcm, dsm, DpmBuilder.directBlockBuild(appId, Constants.DPM.DPM_C_0, Constants.DPM.DPM_D_3), userId, appId, host).buildClick("st_info_click_btn_alipay"));//支付宝提现按钮点击
        result.put("st_info_exposure_btn_initial", new WalletEmbed(dcm, dsm, DpmBuilder.build(appId, Constants.DPM.DPM_B_61, Constants.DPM.DPM_C_1, Constants.DPM.DPM_D_1), userId, appId, host).buildExposure("st_info_exposure_btn_initial"));//获取初始密码按钮曝光
        result.put("st_info_click_btn_initial", new WalletEmbed(dcm, dsm, DpmBuilder.build(appId, Constants.DPM.DPM_B_61, Constants.DPM.DPM_C_1, Constants.DPM.DPM_D_1), userId, appId, host).buildClick("st_info_click_btn_initial"));//获取初始密码按钮点击
        result.put("st_info_exposure_btn_register", new WalletEmbed(dcm, dsm, DpmBuilder.build(appId, Constants.DPM.DPM_B_61, Constants.DPM.DPM_C_1, Constants.DPM.DPM_D_2), userId, appId, host).buildExposure("st_info_exposure_btn_register"));//注册按钮曝光
        result.put("st_info_click_btn_register", new WalletEmbed(dcm, dsm, DpmBuilder.build(appId, Constants.DPM.DPM_B_61, Constants.DPM.DPM_C_1, Constants.DPM.DPM_D_2), userId, appId, host).buildClick("st_info_click_btn_register"));//注册按钮点击
        result.put("st_info_exposure_btn_go_login", new WalletEmbed(dcm, dsm, DpmBuilder.build(appId, Constants.DPM.DPM_B_61, Constants.DPM.DPM_C_1, Constants.DPM.DPM_D_3), userId, appId, host).buildExposure("st_info_exposure_btn_go_login"));//去登陆按钮曝光
        result.put("st_info_click_btn_go_login", new WalletEmbed(dcm, dsm, DpmBuilder.build(appId, Constants.DPM.DPM_B_61, Constants.DPM.DPM_C_1, Constants.DPM.DPM_D_3), userId, appId, host).buildClick("st_info_click_btn_go_login"));//去登陆按钮点击
        result.put("st_info_exposure_btn_go_question", new WalletEmbed(dcm, dsm, DpmBuilder.build(appId, Constants.DPM.DPM_B_61, Constants.DPM.DPM_C_1, Constants.DPM.DPM_D_4), userId, appId, host).buildExposure("st_info_exposure_btn_go_question"));//不登录有什么问题按钮曝光
        result.put("st_info_click_btn_go_question", new WalletEmbed(dcm, dsm, DpmBuilder.build(appId, Constants.DPM.DPM_B_61, Constants.DPM.DPM_C_1, Constants.DPM.DPM_D_4), userId, appId, host).buildClick("st_info_click_btn_go_question"));//不登录有什么问题按钮点击
        result.put("st_info_exposure_btn_go_wallet", new WalletEmbed(dcm, dsm, DpmBuilder.build(appId, Constants.DPM.DPM_B_61, Constants.DPM.DPM_C_2, Constants.DPM.DPM_D_1), userId, appId, host).buildExposure("st_info_exposure_btn_go_wallet"));//进入钱包按钮曝光
        result.put("st_info_click_btn_go_wallet", new WalletEmbed(dcm, dsm, DpmBuilder.build(appId, Constants.DPM.DPM_B_61, Constants.DPM.DPM_C_2, Constants.DPM.DPM_D_1), userId, appId, host).buildClick("st_info_click_btn_go_wallet"));//进入钱包问题按钮点击
        result.put("st_info_exposure_btn_go_register", new WalletEmbed(dcm, dsm, DpmBuilder.build(appId, Constants.DPM.DPM_B_61, Constants.DPM.DPM_C_3, Constants.DPM.DPM_D_1), userId, appId, host).buildExposure("st_info_exposure_btn_go_register"));//立即注册按钮曝光
        result.put("st_info_click_btn_go_register", new WalletEmbed(dcm, dsm, DpmBuilder.build(appId, Constants.DPM.DPM_B_61, Constants.DPM.DPM_C_3, Constants.DPM.DPM_D_1), userId, appId, host).buildClick("st_info_click_btn_go_register"));//立即注册按钮点击
        result.put("st_info_exposure_btn_find_pass", new WalletEmbed(dcm, dsm, DpmBuilder.build(appId, Constants.DPM.DPM_B_61, Constants.DPM.DPM_C_3, Constants.DPM.DPM_D_2), userId, appId, host).buildExposure("st_info_exposure_btn_find_pass"));//找回密码按钮曝光
        result.put("st_info_click_btn_find_pass", new WalletEmbed(dcm, dsm, DpmBuilder.build(appId, Constants.DPM.DPM_B_61, Constants.DPM.DPM_C_3, Constants.DPM.DPM_D_2), userId, appId, host).buildClick("st_info_click_btn_find_pass"));//找回密码按钮点击
        result.put("st_info_exposure_btn_login", new WalletEmbed(dcm, dsm, DpmBuilder.build(appId, Constants.DPM.DPM_B_61, Constants.DPM.DPM_C_3, Constants.DPM.DPM_D_3), userId, appId, host).buildExposure("st_info_exposure_btn_login"));//登陆按钮曝光
        result.put("st_info_click_btn_login", new WalletEmbed(dcm, dsm, DpmBuilder.build(appId, Constants.DPM.DPM_B_61, Constants.DPM.DPM_C_3, Constants.DPM.DPM_D_3), userId, appId, host).buildClick("st_info_click_btn_login"));//登陆按钮点击
        result.put("st_info_exposure_btn_go_question2", new WalletEmbed(dcm, dsm, DpmBuilder.build(appId, Constants.DPM.DPM_B_61, Constants.DPM.DPM_C_3, Constants.DPM.DPM_D_4), userId, appId, host).buildExposure("st_info_exposure_btn_go_question2"));//登陆页面不登录有什么问题按钮曝光
        result.put("st_info_click_btn_go_question2", new WalletEmbed(dcm, dsm, DpmBuilder.build(appId, Constants.DPM.DPM_B_61, Constants.DPM.DPM_C_3, Constants.DPM.DPM_D_4), userId, appId, host).buildClick("st_info_click_btn_go_question2"));//登陆页面不登录有什么问题按钮点击
        result.put("st_info_exposure_btn_submit", new WalletEmbed(dcm, dsm, DpmBuilder.build(appId, Constants.DPM.DPM_B_61, Constants.DPM.DPM_C_4, Constants.DPM.DPM_D_1), userId, appId, host).buildExposure("st_info_exposure_btn_submit"));//提交按钮曝光
        result.put("st_info_click_btn_submit", new WalletEmbed(dcm, dsm, DpmBuilder.build(appId, Constants.DPM.DPM_B_61, Constants.DPM.DPM_C_4, Constants.DPM.DPM_D_1), userId, appId, host).buildClick("st_info_click_btn_submit"));//提交按钮点击
        result.put("st_info_exposure_btn_not_find", new WalletEmbed(dcm, dsm, DpmBuilder.build(appId, Constants.DPM.DPM_B_61, Constants.DPM.DPM_C_4, Constants.DPM.DPM_D_2), userId, appId, host).buildExposure("st_info_exposure_btn_not_find"));//找不到密码按钮曝光
        result.put("st_info_click_btn_not_find", new WalletEmbed(dcm, dsm, DpmBuilder.build(appId, Constants.DPM.DPM_B_61, Constants.DPM.DPM_C_4, Constants.DPM.DPM_D_2), userId, appId, host).buildClick("st_info_click_btn_not_find"));//找不到密码按钮点击
        result.put("st_info_exposure_btn_reget", new WalletEmbed(dcm, dsm, DpmBuilder.build(appId, Constants.DPM.DPM_B_61, Constants.DPM.DPM_C_4, Constants.DPM.DPM_D_3), userId, appId, host).buildExposure("st_info_exposure_btn_reget"));//重新获取初始密码按钮曝光
        result.put("st_info_click_btn_reget", new WalletEmbed(dcm, dsm, DpmBuilder.build(appId, Constants.DPM.DPM_B_61, Constants.DPM.DPM_C_4, Constants.DPM.DPM_D_3), userId, appId, host).buildClick("st_info_click_btn_reget"));//重新获取初始密码按钮点击
        return result;
    }

    @Override
    public Map<String, String> buildGameHallEmbed(String dsm, Long appId, Long userId, String host) {
        Map<String, String> result = new HashMap<>();
        //第一屏获取更多曝光
        result.put("st_info_exposure_btn_more_1", new GameHallEmbed(null, dsm, DpmBuilder.gameHallBuild(appId, Constants.DPM.DPM_C_1, Constants.DPM.DPM_D_1), userId, appId, host).buildExposure("st_info_exposure_btn_record"));
        //第一屏获取更多点击
        result.put("st_info_click_btn_more_1", new GameHallEmbed(null, dsm, DpmBuilder.gameHallBuild(appId, Constants.DPM.DPM_C_1, Constants.DPM.DPM_D_1), userId, appId, host).buildClick("st_info_click_btn_record"));

        //第一屏马上开玩曝光
        result.put("st_info_exposure_btn_do_1", new GameHallEmbed(null, dsm, DpmBuilder.gameHallBuild(appId, Constants.DPM.DPM_C_1, Constants.DPM.DPM_D_2), userId, appId, host).buildExposure("st_info_exposure_btn_more_1"));
        //第一屏马上开玩点击
        result.put("st_info_click_btn_do_1", new GameHallEmbed(null, dsm, DpmBuilder.gameHallBuild(appId, Constants.DPM.DPM_C_1, Constants.DPM.DPM_D_2), userId, appId, host).buildClick("st_info_click_btn_do_1"));

        //第二屏获取更多曝光
        result.put("st_info_exposure_btn_more_2", new GameHallEmbed(null, dsm, DpmBuilder.gameHallBuild(appId, Constants.DPM.DPM_C_2, Constants.DPM.DPM_D_1), userId, appId, host).buildExposure("st_info_exposure_btn_more_2"));
        //第二屏获取更多点击
        result.put("st_info_click_btn_more_2", new GameHallEmbed(null, dsm, DpmBuilder.gameHallBuild(appId, Constants.DPM.DPM_C_2, Constants.DPM.DPM_D_1), userId, appId, host).buildClick("st_info_click_btn_more_2"));

        //第二屏马上开玩曝光
        result.put("st_info_exposure_btn_do_2", new GameHallEmbed(null, dsm, DpmBuilder.gameHallBuild(appId, Constants.DPM.DPM_C_2, Constants.DPM.DPM_D_2), userId, appId, host).buildExposure("st_info_exposure_btn_do_2"));
        //第二屏马上开玩点击
        result.put("st_info_click_btn_do_2", new GameHallEmbed(null, dsm, DpmBuilder.gameHallBuild(appId, Constants.DPM.DPM_C_2, Constants.DPM.DPM_D_2), userId, appId, host).buildClick("st_info_click_btn_do_2"));

        //第三屏获取更多曝光
        result.put("st_info_exposure_btn_more_3", new GameHallEmbed(null, dsm, DpmBuilder.gameHallBuild(appId, Constants.DPM.DPM_C_3, Constants.DPM.DPM_D_1), userId, appId, host).buildExposure("st_info_exposure_btn_more_3"));
        //第三屏获取更多点击
        result.put("st_info_click_btn_more_3", new GameHallEmbed(null, dsm, DpmBuilder.gameHallBuild(appId, Constants.DPM.DPM_C_3, Constants.DPM.DPM_D_1), userId, appId, host).buildClick("st_info_click_btn_more_3"));

        //第三屏马上开玩曝光
        result.put("st_info_exposure_btn_do_3", new GameHallEmbed(null, dsm, DpmBuilder.gameHallBuild(appId, Constants.DPM.DPM_C_3, Constants.DPM.DPM_D_2), userId, appId, host).buildExposure("st_info_exposure_btn_do_3"));
        //第三屏马上开玩点击
        result.put("st_info_click_btn_do_3", new GameHallEmbed(null, dsm, DpmBuilder.gameHallBuild(appId, Constants.DPM.DPM_C_3, Constants.DPM.DPM_D_2), userId, appId, host).buildClick("st_info_click_btn_do_3"));

        //第四屏获取更多曝光
        result.put("st_info_exposure_btn_more_4", new GameHallEmbed(null, dsm, DpmBuilder.gameHallBuild(appId, Constants.DPM.DPM_C_4, Constants.DPM.DPM_D_1), userId, appId, host).buildExposure("st_info_exposure_btn_more_4"));
        //第四屏获取更多点击
        result.put("st_info_click_btn_more_4", new GameHallEmbed(null, dsm, DpmBuilder.gameHallBuild(appId, Constants.DPM.DPM_C_4, Constants.DPM.DPM_D_1), userId, appId, host).buildClick("st_info_click_btn_more_4"));

        //第四屏马上开玩曝光
        result.put("st_info_exposure_btn_do_4", new GameHallEmbed(null, dsm, DpmBuilder.gameHallBuild(appId, Constants.DPM.DPM_C_4, Constants.DPM.DPM_D_2), userId, appId, host).buildExposure("st_info_exposure_btn_do_4"));
        //第四屏马上开玩点击
        result.put("st_info_click_btn_do_4", new GameHallEmbed(null, dsm, DpmBuilder.gameHallBuild(appId, Constants.DPM.DPM_C_4, Constants.DPM.DPM_D_2), userId, appId, host).buildClick("st_info_click_btn_do_4"));

        //兑换按钮
        result.put("st_info_exposure_btn_credit", new GameHallEmbed(null, dsm, DpmBuilder.directBlockBuild(appId, Constants.DPM.DPM_C_0, Constants.DPM.DPM_D_2), userId, appId, host).buildExposure("st_info_exposure_btn_credit"));
        //兑换按钮
        result.put("st_info_click_btn_credit", new GameHallEmbed(null, dsm, DpmBuilder.directBlockBuild(appId, Constants.DPM.DPM_C_0, Constants.DPM.DPM_D_2), userId, appId, host).buildClick("st_info_click_btn_credit"));

        return result;
    }

    @Override
    public JSONObject buildNewGameHallEmbed(String dsm, Long appId, Long userId, String host, Long pageId) {
        JSONObject result = new JSONObject();
        result.put("st_info_exposure_first_choose_game", JSONObject.parseObject(new GameHallEmbed("1019.2.1." +
                pageId, dsm, appId + ".131.2.1", userId,
                appId, host).buildExposure("st_info_exposure_first_choose_game")));
        result.put("st_info_click_first_choose_game", JSONObject.parseObject(new GameHallEmbed("1019.2.1." +
                pageId, dsm, appId + ".131.2.1", userId, appId, host).buildClick("st_info_click_first_choose_game")));

        result.put("st_info_exposure_daily_choose_game", JSONObject.parseObject(new GameHallEmbed("1019.2.1." +
                pageId, dsm, appId + ".131.2.2", userId,
                appId, host).buildExposure("st_info_exposure_daily_choose_game")));
        result.put("st_info_click_daily_choose_game", JSONObject.parseObject(new GameHallEmbed("1019.2.1." +
                pageId, dsm, appId + ".131.2.2", userId, appId, host).buildClick
                ("st_info_daily_first_choose_game")));

        result.put("st_info_exposure_normal_choose_game", JSONObject.parseObject(new GameHallEmbed("1019.2.1." +
                pageId, dsm, appId + ".131.2.3", userId,
                appId, host).buildExposure("st_info_exposure_normal_choose_game")));
        result.put("st_info_click_normal_choose_game", JSONObject.parseObject(new GameHallEmbed("1019.2.1." +
                pageId, dsm, appId + ".131.2.3", userId, appId, host).buildClick
                ("st_info_click_normal_choose_game")));
        return result;
    }


    @Override
    public Map<String,GameHallAnnouncementRsp> getAnnouncement() {
        if (prizeAnnouncementMap == null) {
            prizeAnnouncementMap = new HashMap<>();
            prizeAnnouncementMap.put(0, "%s每天签到获得的金币已经绕游戏大厅%s圈");
            prizeAnnouncementMap.put(1, "%s在泡泡堂单场获得了%s金币奖励，糖果王国对其发起通缉");
            prizeAnnouncementMap.put(2, "%s兑换了%s奖品");
            prizeAnnouncementMap.put(3, "今天已经成功兑换了%s件【%s】！");
            prizeAnnouncementMap.put(4, "%s运筹帷幄在猜猜乐中获得7倍金币奖励");
            prizeAnnouncementMap.put(5, "皂滑弄人，%s的肥皂飞了%s米，击败了全网%s的用户");
            prizeAnnouncementMap.put(6, "%s手速快的飞起，仅用1s达成了拼图成就，领取%s元随机值的现金");
            prizeAnnouncementMap.put(7, "%s连续击杀糖果怪物%s只，拿到了“怪兽收割机”的称号");
            prizeAnnouncementMap.put(8, "本周新增%s款金币奖品，可直接兑换，数量有限先到先得");
        }
        String s1 = stringRedisTemplate.opsForValue().get(CachedKeyUtils.getRedisKey(CacheKey.GAME_HALL_ANNOUNCEMENT));
        if (StringUtils.isBlank(s1)) {
            Random random = new Random();
            int key1 = random.nextInt(8);
            GameHallAnnouncementRsp rsp1 = new GameHallAnnouncementRsp();
            NickNameDto nickNameDto = consumerService.getNextNickName(null);
            setValues(nickNameDto, random, key1, rsp1);
            nickNameDto = consumerService.getNextNickName(nickNameDto.getId());
            GameHallAnnouncementRsp rsp2 = new GameHallAnnouncementRsp();
            int key2 = random.nextInt(8);
            setValues(nickNameDto, random, key2, rsp2);
            nickNameDto = consumerService.getNextNickName(nickNameDto.getId());
            GameHallAnnouncementRsp rsp3 = new GameHallAnnouncementRsp();
            setValues(nickNameDto, random, 8, rsp3);
            List<GameHallAnnouncementRsp> rspList = Arrays.asList(rsp1, rsp2, rsp3);
            stringRedisTemplate.opsForValue().set(CachedKeyUtils.getRedisKey(CacheKey.GAME_HALL_ANNOUNCEMENT),
                    JSONObject.toJSONString(rspList));
            Map<String,GameHallAnnouncementRsp> result = new TreeMap<>();
            result.put("1", rsp1);
            result.put("2", rsp2);
            result.put("3", rsp3);
            return result;
        } else {
            Long m = null;
            boolean needUpdate = false;
            List<GameHallAnnouncementRsp> gameHallAnnouncementRsps = JSONObject.parseArray(s1, GameHallAnnouncementRsp.class);
            Map<String,GameHallAnnouncementRsp> result = new TreeMap<>();
            for (int i = 0; i < gameHallAnnouncementRsps.size(); i++) {
                if (gameHallAnnouncementRsps.get(i).getTime().compareTo(LocalDateTime.now()) <= 0) {
                    needUpdate = true;
                    NickNameDto nickNameDto = consumerService.getNextNickName(m);
                    m=nickNameDto.getId();
                    if (gameHallAnnouncementRsps.get(i).getType() != 3) {
                        GameHallAnnouncementRsp rsp = new GameHallAnnouncementRsp();
                        Random random = new Random();
                        int key2 = random.nextInt(8);
                        setValues(nickNameDto, random, key2, rsp);
                        gameHallAnnouncementRsps.set(i, rsp);
                        result.put((i+1)+"", rsp);
                    } else {
                        GameHallAnnouncementRsp rsp = new GameHallAnnouncementRsp();
                        Random random = new Random();
                        setValues(nickNameDto, random, 8, rsp);
                        gameHallAnnouncementRsps.set(i, rsp);
                        result.put("3", rsp);
                    }
                }else {
                    result.put((i+1)+"", gameHallAnnouncementRsps.get(i));
                }
            }
            if (needUpdate) {
                stringRedisTemplate.opsForValue().set(CachedKeyUtils.getRedisKey(CacheKey.GAME_HALL_ANNOUNCEMENT),
                        JSONObject.toJSONString(gameHallAnnouncementRsps));
            }

            return result;
        }
    }


    private void setValues(NickNameDto nickNameDto, Random random, int key, GameHallAnnouncementRsp rsp1) {
        switch (key){
            case 0 :
                rsp1.setAnnouncement(prizeAnnouncementMap.get(0));
                rsp1.setValues(getList(nickNameDto.getNickName(),String.valueOf(random.nextInt(18)+3)));
                rsp1.setType(1);
                rsp1.setTime(LocalDateTime.now().plusHours(1));
                break;
            case 1:
                rsp1.setAnnouncement(prizeAnnouncementMap.get(1));
                rsp1.setValues(getList(nickNameDto.getNickName(),String.valueOf(random.nextInt(10001) +10000)));
                rsp1.setType(1);
                rsp1.setTime(LocalDateTime.now().plusHours(1));
                break;
            case 2:
                rsp1.setAnnouncement(prizeAnnouncementMap.get(2));
                rsp1.setValues(getList(nickNameDto.getNickName(),prizes.get(random.nextInt(prizes.size()))));
                rsp1.setType(2);
                rsp1.setTime(LocalDateTime.now().plusHours(3));
                break;
            case 3:
                rsp1.setAnnouncement(prizeAnnouncementMap.get(3));
                rsp1.setValues(getList(String.valueOf(random.nextInt(10)+1),prizes.get(random.nextInt(prizes.size()))));
                rsp1.setType(2);
                rsp1.setTime(LocalDateTime.now().plusHours(3));
                break;
            case 4:
                rsp1.setAnnouncement(prizeAnnouncementMap.get(4));
                rsp1.setValues(Collections.singletonList(nickNameDto.getNickName()));
                rsp1.setType(1);
                rsp1.setTime(LocalDateTime.now().plusHours(1));
                break;
            case 5:
                rsp1.setAnnouncement(prizeAnnouncementMap.get(5));
                Integer distance = random.nextInt(126);
                rsp1.setValues(Arrays.asList(nickNameDto.getNickName(), String.valueOf(distance) + 175, String
                        .valueOf(92 + (distance / 17))));
                rsp1.setType(1);
                rsp1.setTime(LocalDateTime.now().plusHours(1));
                break;
            case 6:
                rsp1.setAnnouncement(prizeAnnouncementMap.get(6));
                rsp1.setValues(Arrays.asList(nickNameDto.getNickName(), String.valueOf((random.nextInt(10)/10.0) +0.1)));
                rsp1.setType(1);
                rsp1.setTime(LocalDateTime.now().plusHours(1));
                break;
            case 7:
                rsp1.setAnnouncement(prizeAnnouncementMap.get(7));
                rsp1.setValues(Arrays.asList(nickNameDto.getNickName(), String.valueOf(random.nextInt(51) + 30)));
                rsp1.setType(1);
                rsp1.setTime(LocalDateTime.now().plusHours(1));
                break;
            case 8:
                rsp1.setAnnouncement(prizeAnnouncementMap.get(8));
                rsp1.setValues(Collections.singletonList(String.valueOf(random.nextInt(5) + 1)));
                rsp1.setType(3);
                LocalDate input = LocalDate.now();
                LocalDate nextWed = input.with(TemporalAdjusters.next(DayOfWeek.MONDAY));
                rsp1.setTime(nextWed.atStartOfDay());
                break;
            default:
                break;
        }
    }

    public List<String> getList(String... strs) {
        return Arrays.asList(strs);
    }
}
