package com.tzld.piaoquan.recommend.server.framework.recaller;

import com.tzld.piaoquan.recommend.server.framework.candidiate.Candidate;
import com.tzld.piaoquan.recommend.server.framework.common.User;
import com.tzld.piaoquan.recommend.server.gen.recommend.RecommendRequest;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;


public class FilterPipeline<T> {

    private static final Logger LOGGER = LoggerFactory.getLogger(FilterPipeline.class);
    public int filterNum;
    private final FilterConfig config;
    private final List<AbstractFilter<T>> filters;
    private final RecommendRequest requestContext;
    private final User user;

    public FilterPipeline(FilterConfig config,
                          RecommendRequest requestContext,
                          User user) {

        this.config = config;
        this.requestContext = requestContext;
        this.user = user;
        this.filters = new ArrayList<>();
        this.constructFilters(config);
    }

    public List<AbstractFilter<T>> getFilters() {
        return filters;
    }

    public void constructFilters(FilterConfig config) {
        // add filter
        if (config != null) {
            for (FilterConfigInfo filterConfigInfo : config.getFilterConfigInfoList()) {
                try {
                    AbstractFilter<T> filter = (AbstractFilter) Class.forName(filterConfigInfo.getFilterName())
                            .getConstructor(FilterConfigInfo.class, RecommendRequest.class, User.class)
                            .newInstance(filterConfigInfo, this.requestContext, this.user);

                    this.filters.add(filter);
                } catch (Exception e) {
                    LOGGER.error("Filter config info construct error, [{}] [{}]",
                            filterConfigInfo, ExceptionUtils.getFullStackTrace(e));
                }
            }
        }
    }

    public List<T> doFilter(Candidate candidate, List<T> list) {
        for (AbstractFilter filter : filters) {
            filter.doFilter(candidate, list);
        }
        return list;
    }
}
