package com.tzld.piaoquan.recommend.server.service.recall.strategy;

import com.google.common.collect.Lists;
import com.google.common.reflect.TypeToken;
import com.tzld.piaoquan.recommend.server.model.Video;
import com.tzld.piaoquan.recommend.server.service.filter.FilterResult;
import com.tzld.piaoquan.recommend.server.service.filter.FilterService;
import com.tzld.piaoquan.recommend.server.service.recall.FilterParamFactory;
import com.tzld.piaoquan.recommend.server.service.recall.RecallParam;
import com.tzld.piaoquan.recommend.server.service.recall.RecallStrategy;
import com.tzld.piaoquan.recommend.server.util.CommonCollectionUtils;
import com.tzld.piaoquan.recommend.server.util.JSONUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * @author dyp
 */
@Slf4j
public abstract class AbstractVideoRecallStrategy implements RecallStrategy {
    @Autowired
    @Qualifier("redisTemplate")
    protected RedisTemplate<String, String> redisTemplate;

    @Autowired
    protected FilterService filterService;

    @Override
    public List<Video> recall(RecallParam param) {


        if (param.getVideoId() == null || param.getVideoId() == 0) {
            return Collections.emptyList();
        }
        String recall_key = recallKey(param);
        // [[16687915, 0.5], [16528093, 0.5]]
        String value = redisTemplate.opsForValue().get(recall_key);
        if (StringUtils.isBlank(value)) {
            return Collections.emptyList();
        }
        List<List<String>> videoScores = JSONUtils.fromJson(value, new TypeToken<List<List<String>>>() {
        }, Collections.emptyList());


        Map<Long, Double> videoScoreMap = CommonCollectionUtils.toMap(videoScores, v -> NumberUtils.toLong(v.get(0)),
                v -> NumberUtils.toDouble(v.get(1)));
        List<Video> results = new ArrayList<>();

        FilterResult filterResult = filterService.filter(FilterParamFactory.create(param, Lists.newArrayList(videoScoreMap.keySet())));

        if (filterResult != null && CollectionUtils.isNotEmpty(filterResult.getVideoIds())) {
            filterResult.getVideoIds().stream().forEach(vid -> {
                Video recallData = new Video();
                recallData.setVideoId(vid);
                recallData.setRovScore(videoScoreMap.get(vid));
                recallData.setPushFrom(pushFrom());
                recallData.setFlowPool("");
                results.add(recallData);
            });
        }

        return results;
    }

    abstract String recallKey(RecallParam param);
}
