package com.duiba.tuia.youtui.web.tool;

import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.duiba.tuia.youtui.web.constant.Constants;
import com.duiba.tuia.youtui.web.constant.DmCookieHolder;
import com.google.common.base.Splitter;
import com.google.common.collect.Maps;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * ClassName: CookieUtil <br/>
 * date: 2016年12月5日 下午2:40:27 <br/>.
 *
 * @since JDK 1.6
 */
public class CookieUtil {

    /**
     * The logger.
     */
    private static Logger logger = LoggerFactory.getLogger(CookieUtil.class);

    /**
     * The Constant THE_SUFFIX.
     */
    private static final String THE_SUFFIX = ".duiba.com.cn";

    /**
     * The Constant log.
     */
    private static final Logger log = LoggerFactory.getLogger(CookieUtil.class);

    /**
     * The Constructor.
     */
    private CookieUtil() {
    }

    /**
     * Creates the cookie for ever.
     *
     * @param name the name
     * @param value the value
     * @return the cookie
     */
    private static Cookie createCookieForEver(String name, String value) {
        Cookie cookie = new Cookie(name, value);
        cookie.setPath("/");
        cookie.setMaxAge(10 * 365 * 24 * 60 * 60);
        return cookie;
    }

    /**
     * Creates the session24 cookie.
     *
     * @param name the name
     * @param value the value
     * @return the cookie
     */
    private static Cookie createSession24Cookie(String name, String value) {
        Cookie cookie = new Cookie(name, value);
        cookie.setPath("/");
        cookie.setMaxAge(24 * 60 * 60);
        return cookie;
    }

    /**
     * Creates the session this  day cookie.
     *
     * @param name the name
     * @param value the value
     * @param maxAge cookie生命周期 以秒为单位
     * @return the cookie
     */
    private static Cookie createSessionForTimesCookie(String name, String value, int maxAge) {
        Cookie cookie = new Cookie(name, value);
        cookie.setSecure(false);
        cookie.setPath("/");
        cookie.setMaxAge(maxAge);
        return cookie;
    }


    /**
     * Sets the cross cookie for every.
     *
     * @param name the name
     * @param value the value
     */
    public static void setCrossCookieForEvery(String name, String value) {
        Cookie cookie = createCookieForEver(name, value);
        RequestLocal.get().getResponse().addCookie(cookie);
    }

    /**
     * Sets the cross cookie for24 hour.
     *
     * @param name the name
     * @param value the value
     */
    public static void setCrossCookieFor24Hour(String name, String value) {
        try {
            Cookie cookie = createSession24Cookie(name, URLEncoder.encode(value, "utf-8"));
            RequestLocal.get().getResponse().addCookie(cookie);
        } catch (Exception e) {
            log.warn("error", e);
        }
    }


    /**
     * Sets the cross cookie for times.
     *
     * @param name the name
     * @param value the value
     */
    public static void setCrossCookieForTimes(String name, String value, int times) {
        try {
            Cookie cookie = createSessionForTimesCookie(name, URLEncoder.encode(value, "utf-8"), times);
            RequestLocal.get().getResponse().addCookie(cookie);
        } catch (Exception e) {
            log.warn("error", e);
        }
    }


    /**
     * Creates the cookie.
     *
     * @param name the name
     * @param value the value
     * @return the cookie
     */
    static Cookie createCookie(String name, String value) {
        Cookie cookie = new Cookie(name, value);
        cookie.setPath("/");
        return cookie;
    }

    /**
     * setCookie:(这里用一句话描述这个方法的作用). <br/>
     *
     * @param name the name
     * @param value the value
     * @since JDK 1.6
     */
    public static void setCookie(String name, String value) {
        Cookie cookie = createCookie(name, value);
        RequestLocal.get().getResponse().addCookie(cookie);
    }

    /**
     * 删除通配符级别的cookie.
     *
     * @param name the name
     */
    static void deleteWildcardCookie(String name) {
        Cookie cookie = createCookie(name, null);
        cookie.setMaxAge(0);
        RequestLocal.get().getResponse().addCookie(cookie);
    }

    /**
     * clearWildcardCookie:(这里用一句话描述这个方法的作用). <br/>
     *
     * @since JDK 1.6
     */
    public static void clearWildcardCookie() {

        Cookie cookie = createCookie("jsdata1", null);
        cookie.setMaxAge(0);
        cookie.setDomain(THE_SUFFIX);
        RequestLocal.get().getResponse().addCookie(cookie);

        Cookie cookie2 = createCookie("jsdata2", null);
        cookie2.setMaxAge(0);
        cookie2.setDomain(THE_SUFFIX);
        RequestLocal.get().getResponse().addCookie(cookie2);

        Cookie cookie3 = createCookie("jsdata3", null);
        cookie3.setMaxAge(0);
        cookie3.setDomain(THE_SUFFIX);
        RequestLocal.get().getResponse().addCookie(cookie3);

        Cookie cookie4 = createCookie("loginsToken", null);
        cookie4.setMaxAge(0);
        cookie4.setDomain(THE_SUFFIX);
        RequestLocal.get().getResponse().addCookie(cookie4);

        Cookie cookie5 = createCookie("deap", null);
        cookie5.setMaxAge(0);
        cookie5.setDomain(THE_SUFFIX);
        RequestLocal.get().getResponse().addCookie(cookie5);
    }

    /**
     * 根据名字获取cookie.
     *
     * @param request the request
     * @param name the name
     * @return the cookie by name
     */
    public static Cookie getCookieByName(HttpServletRequest request, String name) {
        Map<String, Cookie> cookieMap = readCookieMap(request);
        if (cookieMap.containsKey(name)) {
            return cookieMap.get(name);
        } else {
            return null;
        }
    }

    /**
     * 将cookie封装到Map里面.
     *
     * @param request the request
     * @return the map< string, cookie>
     */
    private static Map<String, Cookie> readCookieMap(HttpServletRequest request) {
        Map<String, Cookie> cookieMap = new HashMap<>();
        Cookie[] cookies = request.getCookies();
        if (null != cookies) {
            for (Cookie cookie : cookies) {
                cookieMap.put(cookie.getName(), cookie);
            }
        }
        return cookieMap;
    }

    /**
     * 设置cookie.
     *
     * @param response the response
     * @param name cookie名字
     * @param value cookie值
     * @param maxAge cookie生命周期 以秒为单位
     */
    public static void addCookie(HttpServletResponse response, String name, String value, int maxAge) {
        Cookie cookie = new Cookie(name, value);
        cookie.setPath("/");
        if (maxAge > 0) {
            cookie.setMaxAge(maxAge);
        }
        response.addCookie(cookie);
    }

    /**
     * @Description: buildEmbedCookieKey 构造埋点cookieKey
     * eg: _act_172_3590_dsm
     * @Param: [type act or plugin, key dcm or dpm or dsm, slotId, activityId]
     * @Return: java.lang.String
     * @throws:
     * @author: youhaijun
     * @Date: 2017/11/10
     */
    public static String buildEmbedCookieKey(String type, String key, String activityId) {
        return new StringBuilder(type).append("_").append(activityId).append(key).toString();
    }

    public static String getCookie(HttpServletRequest request,String name){
        Cookie cookieByName = getCookieByName(request, name);
        if(cookieByName!=null){
            return cookieByName.getValue();
        }
        return null;
    }


    /**
     * dm：g_actId_dcm,_plu_pluId_dsm,_g_actId_dpm 等埋点数据
     * 放将所有的_g_actId_dcm,_plu_pluId_dsm,_g_actId_dpm等的cookie
     * @param prefix key
     * @param objectKey id
     * @param dsm dsm
     * @param dcm dcm
     * @param dpm dpm
     */
    public static void putDmCookie(String prefix,String objectKey,String dsm,String dcm,String dpm){
        if(StringUtils.isBlank(objectKey)||StringUtils.isBlank(prefix)){
            return;
        }
        dsm = dsm!=null?dsm:StringUtils.EMPTY;
        dcm = dcm!=null?dcm:StringUtils.EMPTY;
        dpm = dpm!=null?dpm:StringUtils.EMPTY;
        //1.先获取所有的key
        Map<String, DmCookieHolder> allDM = getAllDM(prefix);
        DmCookieHolder holder = new DmCookieHolder(objectKey,dsm,dcm,dpm,System.currentTimeMillis());
        if(allDM==null){
            allDM = Maps.newHashMap();
        }
        allDM.put(objectKey,holder);
        String reduce = allDM.values().stream().map(DmCookieHolder::buildString).reduce("", (a, b) -> a + ";" + b);
        String cookieKey = prefix + "_dm";
        setCrossCookieFor24Hour(cookieKey,SecureTool.encryptConsumerCookie(reduce));
    }

    /**
     * 回去某个dm类型的cookie
     * @param prefix 前缀
     * @param objectKey id
     */
    public static DmCookieHolder getDmCookie(String prefix, String objectKey) {
        DmCookieHolder holder = getAllDM(prefix).get(objectKey);
        //兼容处理,从老cookie中取,第二次发布时删除
        if(holder==null){
            HttpServletRequest request = RequestLocal.get().getRequest();
            String dsm = getCookie(request, buildEmbedCookieKey(prefix, Constants.COOKIEKEY.DSM, objectKey));
            String dcm = getCookie(request, buildEmbedCookieKey(prefix, Constants.COOKIEKEY.DCM, objectKey));
            String dpm = getCookie(request, buildEmbedCookieKey(prefix, Constants.COOKIEKEY.DPM, objectKey));
            holder = new DmCookieHolder(objectKey,dsm,dcm,dpm,0L);
        }
        return holder;
    }

    /** 获得cookie中的所有数据 */
    private static Map<String,DmCookieHolder> getAllDM(String prefix){
        HttpServletRequest request = RequestLocal.get().getRequest();
        String cookieKey = prefix + "_dm";
        Cookie cookieByName = getCookieByName(request, cookieKey);
        if(cookieByName==null){
            return Maps.newHashMap();
        }
        String value = cookieByName.getValue();
        try {
            //1.首先解密
            String s = SecureTool.decryptConsumerCookie(value);
            return Splitter.on(";").splitToList(s).stream().map(DmCookieHolder::build)
                    .filter(Objects::nonNull)
                    //如果时间超过了24小时,则删除掉
                    .filter(input->(System.currentTimeMillis()<(input.getCurrentTime()+(24*3600*1000)))).collect(
                            Collectors.toMap(DmCookieHolder::getObjectId, a -> a, (key1, key2) -> key1));
        } catch (Exception e) {
            CookieUtil.deleteWildcardCookie(cookieKey);
            logger.info("parse DmCookie happen error . key:"+prefix+",value:"+value);
        }
        return Maps.newHashMap();
    }

}

