package com.fq.channel.sdk.base.net.req;

import com.fq.channel.sdk.base.constants.AppConfig;
import com.fq.channel.sdk.base.constants.FqConfig;
import com.fq.channel.sdk.base.exception.NullStringToEmptyAdapterFactory;
import com.fq.channel.sdk.base.utils.DES;
import com.fq.channel.sdk.base.utils.DeviceUtils;
import com.fq.channel.sdk.base.utils.EncryptUtils;
import com.fq.channel.sdk.base.utils.Utils;
import com.fq.threelib.gson.Gson;
import com.fq.threelib.gson.GsonBuilder;

import org.json.JSONObject;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Iterator;
import java.util.TreeMap;

import static com.fq.channel.sdk.base.constants.FqConfig.KEY_CHANNEL_TYPE;

/**
 * Created by Ethan on 2017/7/5.
 * 生成请求参数的单例工具类
 */

public class ParamsUtils {

    private ParamsUtils() {
    }

    private volatile static ParamsUtils sInstance;

    public static ParamsUtils getInstance() {
        if (sInstance == null) {
            synchronized (ParamsUtils.class) {
                if (sInstance == null) {
                    sInstance = new ParamsUtils();
                }
            }
        }
        return sInstance;
    }


    /**
     * 生成初始化请求的 对应的Json
     *
     * @return
     */
    public String generateInitParams() {

        ReqContent<ReqInitBody> reqContent = new ReqContent<>();
        //生成init操作的boby
        ReqInitBody body = new ReqInitBody(AppConfig.AD_ID);
        //生成init操作的head
        ReqHeader head = generateReqHeader(body);

        //转换成最终请求用的Json
        reqContent.setHead(head);
        reqContent.setBody(body);

        return gson2Json(reqContent);
    }

    /**
     * 生成登录请求的 对应的Json
     *
     * @return
     */
    public String generateLoginParams(HashMap<String, String> loginOauthInfo) {

        ReqContent<RepLoginBody> reqContent = new ReqContent<>();
        //生成login对象
        RepLoginBody body = new RepLoginBody();
        body.setAdid(FqConfig.get().getAdId());
        body.setChannelId(FqConfig.get().getChannelId());
        //缓存 渠道类型 , 创建订单使用
        String channelType = loginOauthInfo.get("channelType");
        FqConfig.get().put(KEY_CHANNEL_TYPE,channelType);

        body.setChannelType(channelType);
        body.setChannelParams(loginOauthInfo.get("channelParams"));
        //生成login 操作的head
        ReqHeader head = generateReqHeader(body);
        //转换成最终请求用的Json
        reqContent.setHead(head);
        reqContent.setBody(body);

        return gson2Json(reqContent);
    }

    /**
     * 生成订单请求的 对应的Json
     *
     * @return
     */
    public String generateOrderParams(RepOrderBody repOrderBody) {

        ReqContent<RepOrderBody> reqContent = new ReqContent<>();
        //生成init操作的head
        ReqHeader head = generateReqHeader(repOrderBody);

        //转换成最终请求用的Json
        reqContent.setHead(head);
        reqContent.setBody(repOrderBody);

        return gson2Json(reqContent);
    }

    /**
     * 根据对应请求的body生成 对应Json中的head
     *
     * @param reqBody 对应请求的body
     * @param <T>
     * @return 对应请求Json中的head
     */
    private <T> ReqHeader generateReqHeader(T reqBody) {

        ReqHeader reqHeader = new ReqHeader();
        reqHeader.setOsInfo(DeviceUtils.getAndroidVersion() + "_"
                + DeviceUtils.getSDKVersion());  //系统信息

        reqHeader.setModel(DeviceUtils.getModel()); //手机型号
        reqHeader.setNetworkType(Utils.isWifi() ?"1" : "2"); //网络类型 1 wifi   2 其他

        reqHeader.setRequestIp(Utils.getIPAddress(true)); //请求ip
        reqHeader.setImei(AppConfig.sImei); //Android 手机唯一识别码
        reqHeader.setIdfa(""); //ios唯一标识 没有传空字符传
        reqHeader.setOsType("1"); //系统类型 1 安卓 2 IOS 3 web 4 其他

        reqHeader.setAppId(AppConfig.APP_ID); //appId
        reqHeader.setChannelId(AppConfig.CHANNEL_ID); //渠道号
        reqHeader.setAdId(AppConfig.AD_ID); //广告编号
        reqHeader.setAdFlag(AppConfig.AD_FLAG); //广告名
        reqHeader.setSdkVersion(AppConfig.FQ_GAME_SDK_VERSION_CODE);//凤起SDK版本
        reqHeader.setGameVersion(AppConfig.GAME_VERSION);//游戏版本
        reqHeader.setToken(AppConfig.sCurrentToken); //token

        reqHeader.setTdid(AppConfig.sTdADTdid);//Tdid

        String timestamp = System.currentTimeMillis() + "";//时间戳
        reqHeader.setTimestamp(timestamp);

        reqHeader.setVerificationCode(generateSign(reqBody, timestamp));//MD5校验值
        return reqHeader;
    }

    /**
     * 根据相应的ReqBody生成对应的sign
     *
     * @param t         对应的ReqBody
     * @param timestamp 时间戳
     * @param <T>
     * @return
     */
    private <T> String generateSign(T t, String timestamp) {
        try {
            TreeMap<String, String> treeMap = new TreeMap<>();
            Field[] fields = t.getClass().getDeclaredFields();

            //防止加载类
            for (Field field : fields) {
                if (Modifier.isFinal(field.getModifiers()) || Modifier.isStatic(field.getModifiers())){
                    continue;
                }
                field.setAccessible(true);
                String key = field.getName();
                String value = "";
                //不为空的值拼接原来的值
                if (field.get(t) != null) {
//                    value = (String) field.get(t);
                    value = String.valueOf(field.get(t)) ;
                }
                treeMap.put(key, value);
            }

            //拼接有序的数据进行加密
            Iterator<String> iterator = treeMap.keySet().iterator();
            StringBuilder sb = new StringBuilder();
            while (iterator.hasNext()) {
                String key = iterator.next();
                sb.append(key);
                sb.append(treeMap.get(key));
            }

            //加上时间戳
            sb.append(timestamp);
            //生成MD5之后再进行加密
            String md5 = EncryptUtils.encryptMD5ToString(sb.toString());
            String result = DES.encryptDES(md5, md5.substring(md5.length() - 8, md5.length()));
            return result;
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 生成最终请求的json
     *
     * @param reqContent
     * @param <T>
     * @return
     */
    private <T> String gson2Json(ReqContent<T> reqContent) {

        Gson gson = new GsonBuilder()
                .registerTypeAdapterFactory(new NullStringToEmptyAdapterFactory())//这里生成Gson时注册自定义处理String NULL值的TypeAdapter 将null换成""
                .disableHtmlEscaping() //禁止转义JSON等号大括号字符串
                .create();
        return gson.toJson(reqContent);
    }

}
