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

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 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
public abstract class AbstractFilterService {

    private final ExecutorService pool = ThreadPoolFactory.filterPool();

    private List<Long> truncation(List<Long> videoIds, int forceTruncation) {
        if (forceTruncation == 0) {
            return videoIds;
        } else {
            return videoIds.subList(0, Math.min(forceTruncation, videoIds.size()));
        }
    }

    protected 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);
            return null;
        }

        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(SecurityStrategy.class));
        strategies.add(ServiceBeanFactory.getBean(PreViewedStrategy.class));
        strategies.add(ServiceBeanFactory.getBean(ViewedStrategy.class));
        strategies.add(ServiceBeanFactory.getBean(RecommendStatusStrategy.class));
        strategies.add(ServiceBeanFactory.getBean(SupplyExpStrategy.class));
        strategies.add(ServiceBeanFactory.getBean(AppletVideoStatusStrategy.class));
        strategies.add(ServiceBeanFactory.getBean(RiskVideoStrategy.class));
        switch (param.getAppType()) {
            case 0:
            case 4:
                strategies.add(ServiceBeanFactory.getBean(AllowListStrategy.class));
                break;
            case 13:
                break;
            default:
                strategies.add(ServiceBeanFactory.getBean(AllowListStrategy.class));
                strategies.add(ServiceBeanFactory.getBean(TagStrategy.class));
                break;
        }
        if (CollectionUtils.isNotEmpty(param.getAbExpCodes()) && param.getAbExpCodes().contains("697")) {
            strategies.add(ServiceBeanFactory.getBean(VideoSourceTypeStrategy.class));
        }

        return strategies;
    }

}
