package com.diaoyun.zion.master.util;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.text.StringEscapeUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.DataNode;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 处理 Json 的工具类
 *
 * @see Jsoup 处理 Json 的工具包
 * @version 1.0
 */
public class JsoupUtil {

    public static String unknow = "未知";
    private static Logger logger = LoggerFactory.getLogger(JsoupUtil.class);

    /**
     * 获取淘宝商品详情的信息 店铺id 名字 主图 sibUrl 等
     *
     * @param content
     * @return
     */
    public static Map<String, String> getTbItemDetail(String content) {
        String variableName = "g_config";
        String configGroup = getScriptContent(content, variableName);
        Map<String, String> returnMap = new HashMap<>();
        String varArr[] = configGroup.split(";");
        for (String variable : varArr) {
            //获取g_config 变量
            //  Regex for the value of the key
            Pattern variablePattern = Pattern.compile("(g_config){1,1}\\s+={1,1}[\\s\\S]*");
            Matcher varMatcher = variablePattern.matcher(variable);
            while (varMatcher.find()) {
                String configStr = varMatcher.group();
                //获取 sibUrl itemId shopId shopName 获取item里面的数据，包括title pic（主图地址） 这些值都是字符串
                List<String> needInfo = new ArrayList<>();
                needInfo.add("sibUrl");
                needInfo.add("itemId");
                needInfo.add("shopId");
                needInfo.add("shopName");
                needInfo.add("url");
                needInfo.add("pic");
                needInfo.add("title");
                //从返回的字符串中获取变量的值
                getInfoFromJsStr(needInfo, configStr, returnMap);
            }
        }

        /*//加入店铺链接
        if(returnMap.get("shopId")!=null) {
            String shopAddress="https://shop"+returnMap.get("shopId")+".taobao.com/";
            returnMap.put("title",shopAddress);
        }*/
        //unicode 解码
        if (returnMap.get("shopName") != null) {
            //unicode 解码
            String convertStr = StringEscapeUtils.unescapeJava(returnMap.get("shopName"));
            returnMap.put("shopName", convertStr);
        }
        if (returnMap.get("title") != null) {
            //unicode 解码
            String convertStr = StringEscapeUtils.unescapeJava(returnMap.get("title"));
            returnMap.put("title", convertStr);
        }
        return returnMap;
    }

    /**
     * 根据script中的变量名获取script中变量相关的内容
     *
     * @param content
     * @param variableName
     * @return
     */
    public static String getScriptContent(String content, String variableName) {
        // logger.info(content);
        Document document = Jsoup.parse(content);
        Elements elementList = document.getElementsByTag("script");
        String configGroup = null;
        for (Element element : elementList) {
            for (DataNode dataNode : element.dataNodes()) {
                String dataStr = dataNode.getWholeData();
                // 获取带有 g_config 变量的 script 标签
                Pattern p = Pattern.compile("(" + variableName + "){1,1}\\s*={1,1}[\\s\\S]*(;){1,1}");
                Matcher m = p.matcher(dataStr);
                while ((m.find())) {
                    configGroup = m.group();
                }
            }
        }
        return configGroup;
    }

    /**
     * 根据script中的变量名获取script中变量相关的内容，特指天猫的返回信息 没什么用，没有商品的规格信息
     *
     * @param content
     * @return
     */
    @Deprecated
    private static String getTmScriptContent(String content) {
        //logger.info(content);
        Document document = Jsoup.parse(content);
        Elements elementList = document.getElementsByTag("script");
        String configGroup = null;
        for (Element element : elementList) {
            for (DataNode dataNode : element.dataNodes()) {
                String dataStr = dataNode.getWholeData();
                //获取带有 g_config 变量的 script 标签
                Pattern p = Pattern.compile("(TShop.Setup){1,1}[\\s\\S]*?(\\);){1,1}");
                Matcher m = p.matcher(dataStr);
                while ((m.find())) {
                    //System.out.println(m.group());
                    configGroup = m.group();
                    int firstBrackets=configGroup.indexOf("{");
                    int lastbrackets=configGroup.lastIndexOf("}");
                    configGroup=configGroup.substring(firstBrackets,lastbrackets+1);
                }
            }
        }
        return configGroup;
    }

    /**
     * 从返回的字符串中获取变量的值
     *
     * @param needInfo
     * @param configStr
     * @param returnMap
     */
    private static void getInfoFromJsStr(List<String> needInfo, String configStr, Map<String, String> returnMap) {
        for (String info : needInfo) {
            // 获取 相关信息
            String patternStr = "((" + info + "){1,1}?)\\s+(:{1,1}?)[\\s]*(('){1,1}?)[\\S]*(('){1,1}?)";
            Pattern infoPattern = Pattern.compile(patternStr);
            Matcher infoMatcher = infoPattern.matcher(configStr);
            while (infoMatcher.find()) {
                int infoBegin = infoMatcher.group().indexOf("'");
                int infoEnd = infoMatcher.group().lastIndexOf("'");
                String infoValue = infoMatcher.group().substring(infoBegin + 1, infoEnd);
                // 获取 infoValue
                returnMap.put(info, infoValue);
            }
        }
    }

    /**
     * 解析出商品详情
     *
     * @param content
     * @return
     */
    public static Map<String, Object> getPropMap(String content) {
        Map<String, Object> resultMap = new HashMap<>(16);
        Document document = Jsoup.parse(content);
        Element skuElement = document.getElementById("J_isku");
        Elements propList = skuElement.getElementsByClass("J_Prop");
        if (propList == null || propList.size() < 1) {
            resultMap.put("hasSku", false);
        } else {
            getSku(propList, resultMap);
        }
        return resultMap;
    }

    /**
     * 获取sku 对照着返回html来写方法
     *
     * @param propList
     * @param resultMap
     */
    private static void getSku(Elements propList, Map<String, Object> resultMap) {
        for (Element element : propList) {
            //属性描述
            Elements propNameELements = element.getElementsByClass("tb-property-type");
            String propName = JsoupUtil.unknow;
            if (propNameELements != null && propNameELements.size() > 0) {
                propName = propNameELements.get(0).text();
            }

            if (resultMap.get(propName) == null) {
                //防止属性名重复
            } else {
                int random = (int) (Math.random() * 1000);
                propName = propName + random;
            }
            Map<String, Object> skuMap = new HashMap<>();
            resultMap.put(propName, skuMap);

            Elements liList = element.getElementsByTag("li");
            if (liList != null && liList.size() > 0) {
                for (Element liEle : liList) {
                    String propKey = liEle.attr("data-value");
                    Elements spanList = liEle.getElementsByTag("span");
                    Elements aList = liEle.getElementsByTag("a");
                    String title = JsoupUtil.unknow;
                    String image = "";
                    if (liList != null && liList.size() > 0) {
                        title = spanList.get(0).text();
                    }
                    if (liList != null && liList.size() > 0) {
                        image = aList.get(0).attr("style");
                    }
                    Map<String, Object> propMap = new HashMap<>();
                    propMap.put("title", title);
                    propMap.put("image", image);
                    ((Map<String, Object>) resultMap.get(propName)).put(propKey, propMap);
                }
            }
        }
    }

    /**
     * 根据 script id获取内容
     *
     * @param content 网页内容
     * @param id <script>标签的id
     * @return <script>标签内的网页内容
     */
    public static JSONObject getScriptContentById(String content, String id) {
        Document document = Jsoup.parse(content);
        Element element = document.getElementById(id);
        String dataStr = element.data();
        JSONObject dataMap = JSONObject.fromObject(dataStr);
        return dataMap;
    }

    /**
     * 获取指定网页内的 script 标签的 Json 格式的数据变量
     *
     * @param content 网页内容
     * @param variableName 变量名
     * @return 变量内的 Json 数据
     */
    public static JSONObject getItemDetailByName(String content, String variableName) {
        String detailStr = getScriptContent(content, variableName);
        int firstBrackets=detailStr.indexOf("{");
        int lastbrackets=detailStr.lastIndexOf("}");
        detailStr=detailStr.substring(firstBrackets,lastbrackets+1);
        JSONObject dataMap= JSONObject.fromObject(detailStr);
        return dataMap;
    }

    /**
     * 获取指定网页内容的 script 标签内的变量值</br>
     * -- 注意：
     * 1.仅限于格式：</br>
     *      window.produictId = 290000;</br>
     * 2.变量名在网页内容中是唯一的
     * @param content 网页内容
     * @param variableName 变量名
     * @return 变量的值
     */
    public static String getScriptTagVariableContent(String content, String variableName) {
        String detailStr = getScriptContent(content, variableName);
        int firstBrackets = detailStr.indexOf(variableName);
        int lastbrackets = detailStr.indexOf(";");
        detailStr = detailStr.substring(firstBrackets, lastbrackets)
                .replaceAll(variableName, "")
                .replace("=", "").replace("'", "").trim();
        return detailStr;
    }

    /**
     * 获取订单返回的 Json 数据的 href 节点的地址值
     * @param dataMap
     * @return
     */
    public static Map<String, String> getOrderHref(String dataMap) {
        Map<String, String> map = new HashMap<>(5);
        JSONArray dataArr = JSONObject.fromObject(dataMap).getJSONArray("links");
        for (int i = 0; i < dataArr.size(); i++) {
            JSONObject dataObj = dataArr.getJSONObject(i);
            map.put(dataObj.getString("rel"), dataObj.getString("href"));
        }
        return map;
    }

}

