/**
 * 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.dto.ShieldRuleDto;
import cn.com.duiba.tuia.activity.center.api.remoteservice.RemoteShieldRuleService;
import cn.com.duiba.wolf.dubbo.DubboResult;
import cn.com.duibaboot.ext.autoconfigure.accesslog.AccessLogFilter;
import com.duiba.tuia.youtui.web.service.BaseCacheService;
import com.duiba.tuia.youtui.web.service.ShieldRuleService;
import com.duiba.tuia.youtui.web.tool.RequestTool;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.LoadingCache;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * ClassName: ShieldRuleServiceImpl <br/>
 * Function: 屏蔽规则实现. <br/>
 * date: 2017年1月17日 下午4:16:48 <br/>
 *
 * @author cdm
 * @since JDK 1.6
 */
@Service
public class ShieldRuleServiceImpl extends BaseCacheService implements ShieldRuleService, InitializingBean {


    @Autowired
    private RemoteShieldRuleService remoteShieldRuleService;


    private LoadingCache<String,List<ShieldRuleDto>> shieldRuleCache;

    public static final String SHIELD_RULE_CACHE_KEY = "taw-shield-0001";


    @Override
    public boolean checkRequest(HttpServletRequest request) {
        // 1.获取请求IP 和  use_agent
        String ip = RequestTool.getIpAddr(request);
        String userAgent = RequestTool.getUserAgent(request);


        try {
            // 2.查询所有规则
            List<ShieldRuleDto> shieldRuleDtoList =  shieldRuleCache.get(SHIELD_RULE_CACHE_KEY);
            // 3. 规则匹配
            if(shieldRuleDtoList == null || CollectionUtils.isEmpty(shieldRuleDtoList)){
                return true ;// 无过滤规则
            }

            // 循环规则池进行黑名单过滤
            for(ShieldRuleDto dto : shieldRuleDtoList){

                // 如果匹配规则为空，就不匹配
                if(dto.getRuleContent() == null){
                    continue;
                }

                // 命中直接返回
                if(filterShieldRule(dto,ip,userAgent)){
                    AccessLogFilter.putExPair("hit_rule","规则ID="+dto.getId()+";规则类型＝"+dto.getRuleType()+";匹配原则＝"+dto.getRuleCondition()+";规则内容＝"+dto.getRuleContent());
                    return  false ;
                }

            }
        } catch (Exception e) {
            logger.warn("remoteShieldRuleService.getAllList  ==>  get  result fail ",e);
            //  异常就不判断
            return true ;
        }

        return true;
    }


    private Boolean filterShieldRule(ShieldRuleDto dto,String ip,String useAgent){
        // 精确匹配过滤
        if (dto.getRuleCondition() != null && dto.getRuleCondition() == 1){
            // 匹配IP
            if(dto.getRuleType() == 1 ){
                return (dto.getRuleContent() != null && dto.getRuleContent().equals(ip));
            }
            // 匹配use_agent
            if(useAgent !=null  && dto.getRuleType() == 2 ){
                return (dto.getRuleContent() != null && dto.getRuleContent().equals(useAgent));
            }
        }

        // 模糊匹配过滤
        // 匹配use_agent
        if (dto.getRuleCondition() != null && dto.getRuleCondition() == 0 && dto.getRuleType() == 2) {
            return (useAgent != null && useAgent.toLowerCase().contains(dto.getRuleContent().toLowerCase()));
        }

        return false ;
    }

    private List<ShieldRuleDto> getShieldRuleCache(){

        try {
            DubboResult<List<ShieldRuleDto>> dubboResult = remoteShieldRuleService.getAllList();

            if (CollectionUtils.isNotEmpty(dubboResult.getResult())) {
                return dubboResult.getResult();
            }
        }catch (Exception e){
            logger.warn("remoteShieldRuleService.getAllList  ==>  get  result fail ",e);
        }

        return  new ArrayList<>();
    }


    @Override
    public void afterPropertiesSet() throws Exception {
        shieldRuleCache = CacheBuilder.newBuilder()
                .maximumSize(500)//最多存500个
                .refreshAfterWrite(120, TimeUnit.SECONDS)//每120秒刷新缓存
                .build(new com.google.common.cache.CacheLoader<String, List<ShieldRuleDto>>() {

                    @Override
                    public List<ShieldRuleDto> load(String key) throws Exception {
                        return getShieldRuleCache();
                    }
                });

    }
}
