/**
 * Project Name:tuia-youtui-web<br>
 * File Name:ActivityBOImpl.java<br>
 * Package Name:com.duiba.tuia.youtui.web.bo.impl<br>
 * Date:2017年1月17日下午4:16:48<br>
 * Copyright (c) 2017, duiba.com.cn All Rights Reserved.<br>
 */

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


import cn.com.duiba.tuia.activity.center.api.constant.ConfigKey;
import cn.com.duiba.tuia.activity.center.api.constant.EntranceType;
import cn.com.duiba.tuia.activity.center.api.constant.LoginType;
import cn.com.duiba.tuia.activity.center.api.dto.*;
import cn.com.duiba.tuia.activity.center.api.remoteservice.RemoteActivityService;
import cn.com.duiba.tuia.activity.center.api.remoteservice.RemoteAlipayService;
import cn.com.duiba.tuia.activity.center.api.remoteservice.RemoteBuoyService;
import cn.com.duiba.tuia.ssp.center.api.dto.DomainConfigDto;
import cn.com.duiba.tuia.ssp.center.api.dto.GlobalDomainInfoDto;
import cn.com.duiba.tuia.ssp.center.api.dto.SystemConfigDto;
import cn.com.duiba.tuia.ssp.center.api.remote.RemoteActivityTagService;
import cn.com.duiba.tuia.ssp.center.api.remote.RemoteDomainConfigService;
import cn.com.duiba.tuia.ssp.center.api.remote.RemoteDomainInfoService;
import cn.com.duiba.wolf.dubbo.DubboResult;
import cn.com.duiba.wolf.utils.BeanUtils;
import com.dianping.cat.Cat;
import com.duiba.tuia.youtui.web.constant.CacheKey;
import com.duiba.tuia.youtui.web.constant.Constants;
import com.duiba.tuia.youtui.web.constant.ErrorCode;
import com.duiba.tuia.youtui.web.constant.PullDownData;
import com.duiba.tuia.youtui.web.exception.ActivityException;
import com.duiba.tuia.youtui.web.model.ActivityCount;
import com.duiba.tuia.youtui.web.service.ActivityService;
import com.duiba.tuia.youtui.web.service.BaseCacheService;
import com.duiba.tuia.youtui.web.service.SystemConfigService;
import com.duiba.tuia.youtui.web.tool.CachedKeyUtils;
import com.duiba.tuia.youtui.web.tool.StringTool;
import com.google.common.base.Splitter;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

/**
 * ClassName: ActivityBOImpl <br/>
 * Function: 活动业务编排实现. <br/>
 * date: 2017年1月17日 下午4:16:48 <br/>
 *
 * @author leiliang
 * @since JDK 1.6
 */
@Service
public class ActivityServiceImpl extends BaseCacheService implements ActivityService, InitializingBean {

    @Autowired
    private RemoteActivityService remoteActivityService;

    @Autowired
    private RemoteBuoyService remoteBuoyService;

    @Autowired
    private RemoteDomainInfoService remoteDomainInfoService;

    @Autowired
    private RemoteAlipayService remoteAlipayService;

    @Autowired
    private SystemConfigService systemConfigService;

    @Autowired
    private RemoteDomainConfigService remoteDomainConfigService;

    @Autowired
    private cn.com.duiba.tuia.ssp.center.api.remote.RemoteSystemConfigService remoteSystemConfigServiceSsp;

    @Autowired
    private RemoteActivityTagService remoteActivityTagService;

    private LoadingCache<Long, Integer> dojoinEverydayTimes;

    private LoadingCache<Long, TuiaActivityDto> activityCache;

    private LoadingCache<Long, GlobalDomainInfoDto> globalDomain;

    private LoadingCache<Long, List<ActivityOptionDto>> optionsCache;

    private LoadingCache<Long, ActivitySkinDataDto> activitySkinCache;

    private LoadingCache<String, ActivityCount> joinCache;

    private LoadingCache<String, Set<String>> ipWhiteListCache;

    private LoadingCache<List<Long>, Map<Long, Set<Long>>> activityTagCache;

    private LoadingCache<String,List<BuoyDto>> openBuoyCache;

    /**
     * 媒体对应的域名策略
     */
    private LoadingCache<Long, DomainConfigDto> appDomainConfigCache;

    @Override
    public void afterPropertiesSet() {

        appDomainConfigCache = CacheBuilder
                .newBuilder()
                .maximumSize(5000).concurrencyLevel(20).refreshAfterWrite(120, TimeUnit.SECONDS)
                .build(new CacheLoader<Long, DomainConfigDto>() {
                    @Override
                    public DomainConfigDto load(Long appId) throws Exception {
                        return remoteDomainConfigService.selectByAppId(appId);
                    }
                });


        dojoinEverydayTimes = CacheBuilder.newBuilder()
                .maximumSize(500)//最多存500个
                .refreshAfterWrite(10, TimeUnit.SECONDS)//每10秒刷新缓存
                .build(new com.google.common.cache.CacheLoader<Long, Integer>() {

                    @Override
                    public Integer load(Long activityId) {
                        return getDojoinPvCache(activityId);
                    }
                });
        globalDomain = CacheBuilder.newBuilder()
                .maximumSize(5000)//最多存500个
                .refreshAfterWrite(60, TimeUnit.SECONDS)//每1分钟刷新缓存
                .build(new com.google.common.cache.CacheLoader<Long, GlobalDomainInfoDto>() {

                    @Override
                    public GlobalDomainInfoDto load(Long slotId) {
                        return getGlobalDomainInfo(slotId);
                    }
                });

        optionsCache = CacheBuilder
                .newBuilder()
                .maximumSize(500)
                .refreshAfterWrite(10, TimeUnit.MINUTES)//缓存30s刷新一次(load不到新数据时仍返回就数据)
                .build(new com.google.common.cache.CacheLoader<Long, List<ActivityOptionDto>>() {

                    @Override
                    public List<ActivityOptionDto> load(Long activityId) throws Exception {
                        return selectActivityOptions(activityId, false);
                    }
                });

        activitySkinCache = CacheBuilder
                .newBuilder()
                .maximumSize(200)
                .refreshAfterWrite(60, TimeUnit.SECONDS)//缓存60s
                .build(new com.google.common.cache.CacheLoader<Long, ActivitySkinDataDto>() {
                    @Override
                    public ActivitySkinDataDto load(Long activityId) throws Exception {
                        return invokeSelectActivitySkin(activityId);
                    }
                });


        activityCache = CacheBuilder
                .newBuilder()
                .maximumSize(500)
                .refreshAfterWrite(1, TimeUnit.MINUTES)//缓存1分钟刷新一次(load不到新数据时仍返回就数据)
                .expireAfterWrite(10, TimeUnit.MINUTES)//缓存5分钟强制刷新一次
                .build(new com.google.common.cache.CacheLoader<Long, TuiaActivityDto>() {

                    @Override
                    public TuiaActivityDto load(Long activityId) throws Exception {
                        DubboResult<TuiaActivityDto> activityResult = remoteActivityService.getActivity(activityId);
                        if (!activityResult.isSuccess()) {
                            logger.warn("[Tuia-Activity]remoteActivityService.getActivity happen error, and because of=[{}]",
                                    activityId,
                                    activityResult.getMsg());
                            throw new ActivityException(
                                    ErrorCode.E0400001);
                        }

                        TuiaActivityDto activityDto = activityResult.getResult();
                        if (activityDto == null || activityDto.getIsDeleted()) {
                            //活动不存在或 已删除
                            logger.info(" the activity=[{}] non-existent or deleted",
                                    activityId);
                            throw new ActivityException(
                                    ErrorCode.E0400004);
                        }
                        return activityDto;
                    }
                });

        joinCache = CacheBuilder
                .newBuilder()
                .maximumSize(10)
                .refreshAfterWrite(1, TimeUnit.MINUTES)
                .build(new com.google.common.cache.CacheLoader<String, ActivityCount>() {

                    @Override
                    public ActivityCount load(String s) {
                        ActivityCount c = ActivityCount.appear();
                        try {
                            if (c != null) {//系统第一次启动时，数据为null，不记录
                                Cat.logMetricForSum("活动参与率", c.joinRate());
                            }
                        } catch (Exception e) {
                            logger.error(Constants.CAT_ERROR, e);
                        }
                        return ActivityCount.reset();
                    }
                });
        ipWhiteListCache = CacheBuilder.newBuilder()
                .maximumSize(10)//最多存500个
                .refreshAfterWrite(10, TimeUnit.MINUTES)//每10分钟刷新缓存
                .build(new CacheLoader<String, Set<String>>() {
                    @Override
                    public Set<String> load(String key) {
                        return selectIpWhiteList();
                    }
                });

        activityTagCache = CacheBuilder
                .newBuilder()
                .maximumSize(50)
                .refreshAfterWrite(1, TimeUnit.MINUTES)
                .build(new CacheLoader<List<Long>, Map<Long, Set<Long>>>() {
                    @Override
                    public Map<Long, Set<Long>> load(List<Long> activityIds) {
                        return invokeGetActivityTag(activityIds);
                    }
                });
        openBuoyCache = CacheBuilder
                .newBuilder()
                .maximumSize(5)
                .refreshAfterWrite(30, TimeUnit.MINUTES)
                .build(new CacheLoader<String, List<BuoyDto>>() {

                    @Override
                    public List<BuoyDto> load(String key)  {
                        return selectOpenBuoyListRemote();
                    }
                });

    }

    @Override
    public String getActivityTag(Long activityId, Integer activityType) {
        try {
            if (activityType != null && ActivityType.isActivity(activityType)) {
                Set<Long> tag = getActivityTag(activityId);
                if (CollectionUtils.isEmpty(tag)) {
                    return "";
                }
                return StringTool.getStringByList(tag);
            }
            return null;
        } catch (Exception e) {
            logger.warn("get activityTag happen error, the activityId=[{}], and because of=[{}]", activityId, e);
            return null;
        }
    }

    @Override
    public Set<Long> getActivityTag(Long activityId) {
        if (activityId == null) {
            return Collections.emptySet();
        }
        return this.getActivitysTags(Lists.newArrayList(activityId)).get(activityId);
    }

    @Override
    public Map<Long, Set<Long>> getActivitysTags(List<Long> activityIds) {
        try {
            return this.activityTagCache.get(activityIds);
        } catch (Exception e) {
            logger.warn("get activity tag error", e);
            return Collections.emptyMap();
        }
    }

    @Override
    public TuiaActivityDto getActivityById(Long activityId) throws ActivityException {
        try {
            return activityCache.get(activityId);
        } catch (Exception e) {
            throw new ActivityException(e);
        }
    }

    @Override
    public List<TuiaActivityDto> getBatchActivitys(List<Long> activityIds) throws ActivityException {
        if (CollectionUtils.isEmpty(activityIds)) {
            return Collections.emptyList();
        }
        DubboResult<List<TuiaActivityDto>> activityList = remoteActivityService.getActivityList(activityIds);
        if (activityList.isSuccess() && CollectionUtils.isNotEmpty(activityList.getResult())) {
            return activityList.getResult();
        }
        return Collections.emptyList();
    }

    @Override
    public List<ActivityOptionDto> selectActivityOptions(Long activityId, boolean includeStock) {
        DubboResult<List<ActivityOptionDto>> activityOptionResult = remoteActivityService.selectActivityOptionByActivityId(activityId,
                includeStock);
        if (!activityOptionResult.isSuccess()) {
            logger.warn("[Tuia-Activity]remoteActivityService.selectActivityOptionByActivityId happen error, the activityId=[{}], and because of=[{}]",
                    activityId, activityOptionResult.getMsg());
        }

        return activityOptionResult.getResult() == null ? Collections.emptyList() : activityOptionResult.getResult();
    }

    @Override
    public List<ActivityOptionDto> selectActivityOptionsFromCache(Long activityId) {
        try {
            // clone list class
            return BeanUtils.copyList(this.optionsCache.get(activityId), ActivityOptionDto.class);
        } catch (ExecutionException e) {
            logger.warn("optionsCache.get happen error,the activityId = [{}],and because of = [{}]", activityId, e.getMessage());
            return Lists.newArrayList();
        }
    }

    @Override
    public ActivitySkinDataDto selectActivitySkinByActivityId(final long activityId, String login) throws ExecutionException {
        // 线上访问 内存缓存，预览访问接口
        if (LoginType.NORMAL.equalsCode(login)) {
            return activitySkinCache.get(activityId);
        }
        return invokeSelectActivitySkin(activityId);


    }

    private ActivitySkinDataDto invokeSelectActivitySkin(long activityId) {
        ActivitySkinDataDto skin = null;
        try {
            DubboResult<ActivitySkinDataDto> activitySkinDataDtoResult = remoteActivityService.selectActivitySkinByActivityId(activityId);
            if (!activitySkinDataDtoResult.isSuccess()) {
                logger.warn("[Tuia-Activity]remoteActivityService.selectActivitySkinByActivityId happen error, the activityId=[{}], and because of=[{}]",
                        activityId,
                        activitySkinDataDtoResult.getMsg());
            }
            skin = activitySkinDataDtoResult.getResult();
        } catch (Exception e) {
            logger.warn("[Tuia-Activity]remoteActivityService.selectActivitySkinByActivityId happen error, the activityId=[{}]", activityId, e);

        }
        return skin == null ? ActivitySkinDataDto.EMPTY_DTO : skin;

    }

    @Override
    public SkinTemplateDataDto selectSkinTemplateBySkinType(final String skinType) throws ActivityException {
        return advancedCacheClient.getWithCacheLoader(CachedKeyUtils.getRedisKey(CacheKey.SKIN_TEMPLATE_KEY, skinType),
                ONE_HOUR, TimeUnit.SECONDS,
                () -> {
                    DubboResult<SkinTemplateDataDto> skinTemplateDataDtoResult = remoteActivityService.selectSkinTemplateBySkinType(skinType);
                    if (!skinTemplateDataDtoResult.isSuccess()) {
                        logger.warn("[Tuia-Activity]remoteActivityService.selectSkinTemplateBySkinType happen error, the skinType=[{}], and because of=[{}]",
                                skinType,
                                skinTemplateDataDtoResult.getMsg());
                    }
                    return skinTemplateDataDtoResult.getResult();
                });
    }

    @Override
    public ActivityOptionDto selectActivityOption(long optionId) {
        DubboResult<ActivityOptionDto> activityOptionResult = remoteActivityService.selectActivityOption(optionId);
        if (!activityOptionResult.isSuccess()) {
            logger.warn("[Tuia-Activity]remoteActivityService.selectActivityOption happen error, the optionId=[{}], and because of=[{}]",
                    optionId, activityOptionResult.getMsg());
        }
        return activityOptionResult.getResult();
    }

    @Override
    public BuoyDto selectBuoy(Long buoyId) throws ActivityException {

        DubboResult<BuoyDto> result = remoteBuoyService.selectById(buoyId);
        if (!result.isSuccess()
                || null == result.getResult()) {
            logger.warn("[Tuia-Activity]remoteBuoyService.selectById happen error, and because of=[{}]",
                    result.getMsg());
        }
        BuoyDto buoy = result.getResult();
        if (buoy.getIsDeleted() || !buoy.getIsOpen()) {
            throw new ActivityException(ErrorCode.E9999999.geteCode(), "浮标[" + buoy.getId() + "]不存在");
        }
        return buoy;
    }

    @Override
    public List<BuoyDto> selectOpenBuoyList() throws ActivityException {

        try {
            return openBuoyCache.get("selectOpenBuoyList");//唯一字符串，不会改变
        } catch (Exception e) {
            throw new ActivityException(e);
        }
    }


    public List<BuoyDto> selectOpenBuoyListRemote() {
        DubboResult<List<BuoyDto>> result = remoteBuoyService.selectOpenList();
        if (!result.isSuccess()
                || null == result.getResult()) {
            logger.warn("[Tuia-Activity]remoteBuoyService.selectOpenList happen error, and because of=[{}]",
                    result.getMsg());
        }
        return result.getResult();
    }


    @Override
    public ProbDto selectProb(final int entranceType) throws ActivityException {

        DubboResult<ProbDto> result = remoteBuoyService.selectProb(EntranceType.getEntranceType(entranceType));
        if (!result.isSuccess()) {
            logger.warn("[Tuia-Activity]remoteBuoyService.selectProb happen error, and because of=[{}]",
                    result.getMsg());
        }
        return result.getResult();
    }

    @Override
    public void updateReturnTimes(Long slotId, Long consumerId) throws ActivityException {
        String key = CachedKeyUtils.getRedisKey(CacheKey.RETURN_CONSUMER_TIMES_KEY, slotId, consumerId, new DateTime().getDayOfMonth());
        ValueOperations<String, String> ops = redisTemplate03.opsForValue();
        Long increment = ops.increment(key, 1);
        if (1 == increment.intValue()) {
            redisTemplate03.expire(key, getRestSecondsToday(), TimeUnit.SECONDS);
        }
    }

    @Override
    public int getReturnTimes(Long slotId, Long consumerId) throws ActivityException {
        String key = CachedKeyUtils.getRedisKey(CacheKey.RETURN_CONSUMER_TIMES_KEY, slotId, consumerId, new DateTime().getDayOfMonth());
        String value = redisTemplate03.opsForValue().get(key);
        if (StringUtils.isNotEmpty(value)) {
            return Integer.valueOf(value);
        }
        return 0;
    }

    @Override
    public int updateConsumerActivityDojoinCache(Long activityId, Long consumerId) {
        String key = CachedKeyUtils.getRedisKey(CacheKey.CONSUMER_ACTIVITY_DOJOIN_CACHE_KEY, consumerId, new DateTime().getDayOfMonth());
        Long time = redisTemplate03.opsForHash().increment(key, activityId.toString(), 1);
        if (1 == time.intValue()) {
            redisTemplate03.expire(key, getRestSecondsToday(), TimeUnit.SECONDS);
        }
        return time.intValue();

    }

    @Override
    public int getConsumerActivityDojoinCache(Long activityId, Long consumerId) {
        String key = CachedKeyUtils.getRedisKey(CacheKey.CONSUMER_ACTIVITY_DOJOIN_CACHE_KEY, consumerId, new DateTime().getDayOfMonth());
        Object o = redisTemplate03.opsForHash().get(key, activityId.toString());
        if (o != null) {
            return Integer.valueOf(o.toString());
        }
        return 0;
    }

    @Override
    public Map<Object, Object> getConsumerActivityDojoinCacheMap(Long consumerId) {
        String key = CachedKeyUtils.getRedisKey(CacheKey.CONSUMER_ACTIVITY_DOJOIN_CACHE_KEY, consumerId, new DateTime().getDayOfMonth());
        Map<Object, Object> entries = redisTemplate03.opsForHash().entries(key);
        if (MapUtils.isNotEmpty(entries)) {
            return entries;
        }
        return MapUtils.EMPTY_MAP;
    }

    @Override
    public void updateDojoinPvCache(Long activityId) {
        String key = CachedKeyUtils.getRedisKey(CacheKey.DOJOIN_PV_CACHE_KEY, activityId, new DateTime().getDayOfMonth());
        Long dojoinPv = stringRedisTemplate.opsForValue().increment(key, 1);
        if (dojoinPv == 1L) {
            stringRedisTemplate.expire(key, getRestSecondsToday(), TimeUnit.SECONDS);
        }

    }

    @Override
    public int getDojoinPvCache(Long activityId) {
        String key = CachedKeyUtils.getRedisKey(CacheKey.DOJOIN_PV_CACHE_KEY, activityId, new DateTime().getDayOfMonth());
        Object o = stringRedisTemplate.opsForValue().get(key);
        if (o != null) {
            return Integer.valueOf(o.toString());
        }
        return 0;
    }

    @Override
    public void updatePhysicalDailyLimit(Long activityId, Long optionId) {
        String key = CachedKeyUtils.getRedisKey(CacheKey.PHYSICAL_DAILY_LIMIT_KEY, activityId, optionId, new DateTime().getDayOfMonth());

        Long physicalNum = stringRedisTemplate.opsForValue().increment(key, 1);
        if (physicalNum == 1L) {
            stringRedisTemplate.expire(key, getRestSecondsToday(), TimeUnit.SECONDS);
        }
    }

    @Override
    public int getPhysicalDailyLimit(Long activityId, Long optionId) {
        String key = CachedKeyUtils.getRedisKey(CacheKey.PHYSICAL_DAILY_LIMIT_KEY, activityId, optionId, new DateTime().getDayOfMonth());
        Object o = stringRedisTemplate.opsForValue().get(key);
        if (o != null) {
            return (int) o;
        }
        return 0;
    }

    @Override
    public void updatePrizeWinConsumers(Long optionId, String deviceId, String ip) {
        String key = CachedKeyUtils.getRedisKey(CacheKey.PRIZE_WIN_CONSUMERS_KEY, optionId, new DateTime().getDayOfMonth());
        stringRedisTemplate.opsForSet().add(key, deviceId, ip);
        stringRedisTemplate.expire(key, getTomorrowCalmTimeRestSeconds(), TimeUnit.SECONDS);

    }

    @Override
    public void updatePrizeWinConsumersWeek(Long optionId, String deviceId, String ip) {
        String key = CachedKeyUtils.getRedisKey(CacheKey.PRIZE_WIN_WEEK_CONSUMERS_KEY, optionId, new DateTime().getWeekOfWeekyear());
        stringRedisTemplate.opsForSet().add(key, deviceId, ip);
        stringRedisTemplate.expire(key, getNextWeekCalmTimeRestSeconds(), TimeUnit.SECONDS);
    }

    @Override
    public boolean isHaveWonPrizeDay(Long optionId, String deviceId, String ip) {
        int day = new DateTime().getDayOfMonth();
        String key = CachedKeyUtils.getRedisKey(CacheKey.PRIZE_WIN_CONSUMERS_KEY, optionId, day);

        return stringRedisTemplate.opsForSet().isMember(key, deviceId) || (!ipWhite(ip) && stringRedisTemplate.opsForSet().isMember(key, ip));
    }

    /*
     * 是否ip白名单
     */
    private boolean ipWhite(String ip) {
        try {
            return ipWhiteListCache.get("ip").contains(ip);
        } catch (ExecutionException e) {
            logger.warn("", e);
        }
        return false;
    }

    @Override
    public int getDojoinPvDelay(Long activityId) throws ExecutionException {
        return dojoinEverydayTimes.get(activityId);
    }

    @Override
    public Map<Long, Integer> showCache() {
        return dojoinEverydayTimes.asMap();
    }

    @Override
    public int incrAlipayDailyBudget(Long optionId, int amount) {
        String key = CachedKeyUtils.getRedisKey(CacheKey.ALIPAY_DAILY_BUDGET_KEY, optionId, new DateTime().getDayOfMonth());

        Long budget = stringRedisTemplate.opsForValue().increment(key, amount);
        stringRedisTemplate.expire(key, getRestSecondsToday(), TimeUnit.SECONDS);
        return budget.intValue();
    }

    @Override
    public boolean isHaveWonPrizeWeek(Long optionId, String deviceId, String ip) {
        int week = new DateTime().getWeekOfWeekyear();
        String key = CachedKeyUtils.getRedisKey(CacheKey.PRIZE_WIN_WEEK_CONSUMERS_KEY, optionId, week);

        return stringRedisTemplate.opsForSet().isMember(key, deviceId) || (!ipWhite(ip) && stringRedisTemplate.opsForSet().isMember(key, ip));
    }

    @Override
    public void updateAdvertTimes(String location) throws ActivityException {
        String key = CachedKeyUtils.getRedisKey(CacheKey.COUNT_CENTER_ADVERT, location);
        ValueOperations<String, String> ops = redisTemplate03.opsForValue();
        Long increment = ops.increment(key, 1);
        if (1 == increment.intValue()) {
            redisTemplate03.expire(key, getRestSecondsToday(), TimeUnit.SECONDS);
        }
    }

    @Override
    public int getAdvertTimes(String location) throws ActivityException {
        String key = CachedKeyUtils.getRedisKey(CacheKey.COUNT_CENTER_ADVERT, location);
        String value = redisTemplate03.opsForValue().get(key);
        if (StringUtils.isNotEmpty(value)) {
            return Integer.valueOf(value);
        }
        return 0;
    }

    @Override
    public String getLandUrl(Long slotId) {

        try {
            GlobalDomainInfoDto domainRes = globalDomain.get(slotId);
            if (domainRes != null && domainRes.getLandUrl() != null) {
                return domainRes.getLandUrl();
            }
        } catch (Exception e) {
            logger.info("globalDomain.get is  fail , this  slot id is " + slotId);
        }

        return null;
    }

    @Override
    public String getLandUrlByAppId(Long appId) {
        try {
            DomainConfigDto domainConfigDto = appDomainConfigCache.get(appId);
            if (domainConfigDto != null && !StringUtils.isEmpty(domainConfigDto.getLandUrl())) {
                return domainConfigDto.getLandUrl();
            } else {
                DubboResult<SystemConfigDto> systemConfigDtoDubboResult = remoteSystemConfigServiceSsp.selectByKey("tuia-activity-url");
                SystemConfigDto systemConfigDto = systemConfigDtoDubboResult.getResult();
                if (systemConfigDto != null && !StringUtils.isEmpty(systemConfigDto.getEngUrl())) {
                    return systemConfigDto.getLandUrl();
                }
            }
        } catch (Exception e) {
            logger.info("根据媒体获取域名策略信息异常，appId={}" + appId);
        }
        return null;
    }

    @Override
    public void indexCount() {
        try {
            ActivityCount activityCount = this.joinCache.get("activity");
            activityCount.getIndexCount().increment();
        } catch (Exception e) {
            logger.info("ActivityServiceImpl.indexCount，error");
        }
    }

    @Override
    public void doJoinCount() {
        try {
            ActivityCount activityCount = this.joinCache.get("activity");
            activityCount.getJoinCount().increment();
        } catch (Exception e) {
            logger.info("ActivityServiceImpl.doJoinCount，error");
        }

    }


    private GlobalDomainInfoDto getGlobalDomainInfo(Long slotId) {
        try {
            DubboResult<GlobalDomainInfoDto> domainRes = remoteDomainInfoService.selectLandAndMidUrlBySlotId(slotId);
            if (domainRes.getResult() != null && domainRes.isSuccess()) {
                return domainRes.getResult();
            }
        } catch (Exception e) {
            logger.info("remoteDomainInfoService.selectLandAndMidUrlBySlotId  is fail , slot id is " + slotId);
        }
        return new GlobalDomainInfoDto();
    }

    @Override
    public int isPullDown(Long slotId, Long activityId, int joinTimes) {
        //临时功能，参与>=6次才能出下拉推荐位
        if (joinTimes < 6) {
            return 0;
        }
        //根据广告位，活动判断是否出下拉推荐位
        return PullDownData.isPullDown(slotId, activityId);
    }


    private Set<String> selectIpWhiteList() {
        Set<String> rs;
        String ips = this.systemConfigService.getSystemConfig(ConfigKey.IP_WHITE_LIST.getKey());
        if (StringUtils.isNotBlank(ips)) {
            rs = Sets.newHashSet(ips.split(","));
        } else {
            rs = Collections.emptySet();
        }

        return rs;
    }

    private Map<Long, Set<Long>> invokeGetActivityTag(List<Long> activityIds){
        if (CollectionUtils.isEmpty(activityIds)) {
            return Collections.emptyMap();
        }
        return this.remoteActivityTagService.findTagByActivityId(activityIds);
    }

    @Override
    public void refreshCache(String cacheName, String key) {
        if(Objects.equals("optionsCache",cacheName)&&StringUtils.isNotBlank(key)){
            Splitter.on("_").splitToList(key).forEach(i -> this.optionsCache.refresh(Long.valueOf(i)));
        }else if(Objects.equals("openBuoyCache",cacheName)){
            this.openBuoyCache.refresh("selectOpenBuoyList");
        }

    }
}
