package com.tzld.piaoquan.recommend.server.service.filter;

import com.ctrip.framework.apollo.spring.annotation.ApolloJsonValue;
import com.google.common.collect.Lists;
import com.tzld.piaoquan.recommend.server.common.ThreadPoolFactory;
import com.tzld.piaoquan.recommend.server.service.ServiceBeanFactory;
import com.tzld.piaoquan.recommend.server.service.filter.strategy.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.RandomUtils;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

/**
 * @author dyp
 */
@Slf4j
@Component
public class FilterService {

    private final ExecutorService pool = ThreadPoolFactory.filterPool();
    @ApolloJsonValue("${filter_exp_config:{}}")
    private Map<String, Integer> filterExpConfig;

    public FilterResult filter(FilterParam param) {
        List<Long> videoIds = viewFilter(param);
        return new FilterResult(videoIds);
    }

    private List<Long> viewFilter(FilterParam param) {

        List<FilterStrategy> strategies = getStrategies(param);
        CountDownLatch cdl = new CountDownLatch(strategies.size());
        List<Future<List<Long>>> futures = new ArrayList<>();
        for (final FilterStrategy strategy : strategies) {
            Future<List<Long>> future = pool.submit(() -> {
                List<Long> result = strategy.filter(param);
                cdl.countDown();
                return result;
            });
            futures.add(future);
        }
        try {
            cdl.await(1000, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            log.error("filter error", e);
            Thread.currentThread().interrupt();
            return Collections.emptyList();
        }

        List<List<Long>> videoIds = new ArrayList<>();
        for (Future<List<Long>> f : futures) {
            try {
                videoIds.add(f.get());
            } catch (Exception e) {
                log.error("future get error ", e);
            }
        }
        if (CollectionUtils.isEmpty(videoIds)) {
            return Collections.emptyList();
        }
        List<Long> result = Lists.newArrayList(param.getVideoIds());
        for (int i = 0; i < videoIds.size(); ++i) {
            result.retainAll(videoIds.get(i));
        }
        return result;
    }

    private List<FilterStrategy> getStrategies(FilterParam param) {
        List<FilterStrategy> strategies = new ArrayList<>();
        strategies.add(ServiceBeanFactory.getBean(PreViewedStrategy.class));
        strategies.add(ServiceBeanFactory.getBean(ViewedStrategy.class));
        strategies.add(ServiceBeanFactory.getBean(RecommendStatusStrategy.class));
        strategies.add(ServiceBeanFactory.getBean(AppletVideoStatusStrategy.class));
        strategies.add(ServiceBeanFactory.getBean(RiskVideoStrategy.class));

        // UGC视频过滤
        Integer ugcFilterWeight = filterExpConfig.get("userupload");
        if (ugcFilterWeight != null && ugcFilterWeight != 0) {
            int rand = RandomUtils.nextInt(0, 100);
            if (ugcFilterWeight >= 100 || rand < ugcFilterWeight) {
                // log.info("hit ugc filter weight:{} rand:{}", ugcFilterWeight, rand);
                strategies.add(ServiceBeanFactory.getBean(VideoSourceTypeStrategy.class));
            }
        }

        // 全面spider视频过滤
        Integer allSpiderFilterWeight = filterExpConfig.get("allspider");
        if (allSpiderFilterWeight != null && allSpiderFilterWeight != 0) {
            int rand = RandomUtils.nextInt(0, 100);
            if (allSpiderFilterWeight >= 100 || rand < allSpiderFilterWeight) {
                // log.info("hit all spider filter weight:{} rand:{}", allSpiderFilterWeight, rand);
                strategies.add(ServiceBeanFactory.getBean(GeneralSpiderStrategy.class));
            }
        }

//        if (CollectionUtils.isNotEmpty(param.getAbExpCodes()) && param.getAbExpCodes().contains("697")) {
//            strategies.add(ServiceBeanFactory.getBean(VideoSourceTypeStrategy.class));
//        }
//        //全面spider视频过滤
//        if (CollectionUtils.isNotEmpty(param.getAbExpCodes()) && param.getAbExpCodes().contains("722")) {
//            strategies.add(ServiceBeanFactory.getBean(GeneralSpiderStrategy.class));
//        }

        return strategies;
    }

}
