package com.iamberry.app.tool.util;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeMap;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;

import org.apache.commons.lang3.StringUtils;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.iamberry.app.tool.dto.TuyaDTO;
import com.iamberry.app.tool.dto.TuyaHistoryRawDTO;
import com.iamberry.app.tool.dto.TuyaHistoryResultDTO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class TuyaConnector {

	private final static String CLIENT_ID = "5kkyurvvtt58bbuxueee";
	private final static String SECRET_KEY = "rhj6na6u3y6uhy6qrbb3944mg5uqqpbb";

	private static Logger logger = LoggerFactory.getLogger(TuyaConnector.class);

	//调试环境
	// private final static String DOMAIN_NAME = "https://a1.mb.cn.wgine.com/api.json";

	// 生产环境
//	private final static String DOMAIN_NAME = "https://a1.mb.airtakeapp.com/api.json";

	// 国外环境
//	 private final static String DOMAIN_NAME = "https://a1.tuyaus.com/api.json";
	
	// 国外环境
	private final static String DOMAIN_NAME = "https://a1.tuyaus.com/api.json";

	public static void TuyaSyncConnect(String encryptUsername, String userCode) {
		String areacode = "86";
		
		if(encryptUsername.indexOf(",") != -1){
			areacode = StringUtils.substringBefore(encryptUsername, ",");
			encryptUsername = StringUtils.substringAfter(encryptUsername, ",");
		}
		
		userCode = TuyaMD5Util.getMD5(userCode);
		TuyaDTO tuyaDTO = setTuyaDTO();

		tuyaDTO.setApi("tuya.cloud.user.uid.sync");
		tuyaDTO.setData("{\"countryCode\":\""+areacode+"\",\"uid\":\"" + encryptUsername + "\",\"passwd\":\"" + userCode + "\"}");

		String s = getSign(tuyaDTO, SECRET_KEY);
		String sign = TuyaMD5Util.getMD5(s.getBytes());

		String url = DOMAIN_NAME + "?a=" + tuyaDTO.getApi() + "&appVersion=" + tuyaDTO.getAppVersion() + "&clientId="
				+ CLIENT_ID + "&deviceId=" + tuyaDTO.getDeviceid() + "&lang=" + tuyaDTO.getLang() + "&os="
				+ tuyaDTO.getOs() + "&postData=" + tuyaDTO.getData() + "&sid=" + tuyaDTO.getSession() + "&time="
				+ tuyaDTO.getT() + "&ttid=" + tuyaDTO.getTtid() + "&v=" + tuyaDTO.getApiVersion() + "&sign=" + sign;

		try {
			trustAllHttpsCertificates();
			HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
				public boolean verify(String hostname, SSLSession session) {
					// System.out.println("Warning: URL Host: " + hostname + "
					// vs. " + session.getPeerHost());
					return true;
				}
			});
			System.out.println("涂鸦返回数据:" + sendPost(url));
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	public static TuyaHistoryResultDTO TuyaHistoryConnect(long startTime, long endTime, String offset, int limit) {
		ObjectMapper mapper = new ObjectMapper();
		TuyaHistoryRawDTO tuyaData = null;
		TuyaDTO tuyaDTO = setTuyaDTO();

		tuyaDTO.setApi("tuya.cloud.dp.history.get");
		tuyaDTO.setData("{\"productId\":\"" + "4Ic6GgKI0vUG65Jd" + "\",\"dpId\":\"" + 12 + "\",\"startTime\":"
				+ startTime + ",\"endTime\":" + endTime + ",\"offset\":\"" + offset + "\",\"limit\":" + limit + "}");
logger.info("setData:" + tuyaDTO.getData());
		String s = getSign(tuyaDTO, SECRET_KEY);
		String sign = TuyaMD5Util.getMD5(s.getBytes());

		String url = DOMAIN_NAME + "?a=" + tuyaDTO.getApi() + "&appVersion=" + tuyaDTO.getAppVersion() + "&clientId="
				+ CLIENT_ID + "&deviceId=" + tuyaDTO.getDeviceid() + "&lang=" + tuyaDTO.getLang() + "&os="
				+ tuyaDTO.getOs() + "&postData=" + tuyaDTO.getData() + "&sid=" + tuyaDTO.getSession() + "&time="
				+ tuyaDTO.getT() + "&ttid=" + tuyaDTO.getTtid() + "&v=" + tuyaDTO.getApiVersion() + "&sign=" + sign;

		try {
			trustAllHttpsCertificates();
			HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
				public boolean verify(String hostname, SSLSession session) {
					// System.out.println("Warning: URL Host: " + hostname + "
					// vs. " + session.getPeerHost());
					return true;
				}
			});

			tuyaData = mapper.readValue(sendPost(url), TuyaHistoryRawDTO.class);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return tuyaData != null ? tuyaData.getResult() : null;
	}

	private static TuyaDTO setTuyaDTO() {
		TuyaDTO tuyaDTO = new TuyaDTO();
		tuyaDTO.setApiVersion("1.0");
		tuyaDTO.setLang("cn");
		tuyaDTO.setDeviceid("cloud");
		tuyaDTO.setAppVersion("1.0");
		tuyaDTO.setTtid("ios");
		tuyaDTO.setOs("ios");
		tuyaDTO.setClientId(CLIENT_ID);

		tuyaDTO.setT(String.valueOf(System.currentTimeMillis() / 1000));
		tuyaDTO.setSession("abcededdddd");
		return tuyaDTO;
	}

	private static TreeMap<String, String> paramsBuild(TuyaDTO tuyaDTO) {
		TreeMap<String, String> params = new TreeMap<String, String>();
		params.put("a", tuyaDTO.getApi());
		params.put("v", tuyaDTO.getApiVersion());
		params.put("lang", tuyaDTO.getLang());
		params.put("deviceId", tuyaDTO.getDeviceid());
		params.put("appVersion", tuyaDTO.getAppVersion());
		params.put("ttid", tuyaDTO.getTtid());
		params.put("os", tuyaDTO.getOs());
		params.put("clientId", tuyaDTO.getClientId());
		params.put("time", tuyaDTO.getT());
		if (StringUtils.isNotBlank(tuyaDTO.getSession())) {
			params.put("sid", tuyaDTO.getSession());
		}
		if (StringUtils.isNotBlank(tuyaDTO.getData())) {
			params.put("postData", tuyaDTO.getData());
		}
		return params;
	}

	private static String signAssembly(TreeMap<String, String> params, String secretKey) {
		StringBuilder str = new StringBuilder();
		str.append(secretKey);
		Set<String> keySet = params.keySet();
		Iterator<String> iter = keySet.iterator();
		while (iter.hasNext()) {
			String key = iter.next();
			if (StringUtils.isBlank(params.get(key))) {
				continue;
			}
			str.append(key);
			str.append("=");
			str.append(params.get(key));
			str.append("|");
		}
		String strValue = str.toString();
		strValue = strValue.substring(0, (strValue.length() - 1));
		// System.out.println(strValue);
		return strValue;
	}

	private static String getSign(TuyaDTO tuyaDTO, String secretKey) {
		TreeMap<String, String> params = paramsBuild(tuyaDTO);
		String signString = signAssembly(params, secretKey);
		return signString;
	}

	public static boolean signValidate(TuyaDTO tuyaDTO) {
		String secretKey = tuyaDTO.getHashKey();
		String signString = getSign(tuyaDTO, secretKey);
		String sign = TuyaMD5Util.getMD5(signString.getBytes());
		if (tuyaDTO.getOpenSign() && !sign.equals(tuyaDTO.getSign().trim())) {
			return false;
		}
		return true;
	}

	private static String sendPost(String url) throws Exception {
		// 处理+号
		URL obj = new URL(url.replace("+", "%2B"));

		HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();

		con.setRequestMethod("POST");
		con.setRequestProperty("Content-Type", "application/json");
		con.setRequestProperty("accept", "*/*");
		con.setRequestProperty("connection", "Keep-Alive");

		con.setDoOutput(true);
		con.setDoInput(true);

		int responseCode = con.getResponseCode();

		BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
		String inputLine;
		StringBuffer response = new StringBuffer();

		while ((inputLine = in.readLine()) != null) {
			response.append(inputLine);
		}
		in.close();

		// System.out.println("\nSending 'POST' request to URL : " + url);
		// System.out.println("Response Code : " + responseCode);
		// System.out.println("response: " + response.toString());

		return response.toString();
	}

	private static void trustAllHttpsCertificates() throws Exception {
		javax.net.ssl.TrustManager[] trustAllCerts = new javax.net.ssl.TrustManager[1];
		javax.net.ssl.TrustManager tm = new miTM();
		trustAllCerts[0] = tm;
		javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext.getInstance("SSL");
		sc.init(null, trustAllCerts, null);
		javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
	}

	static class miTM implements javax.net.ssl.TrustManager, javax.net.ssl.X509TrustManager {
		public java.security.cert.X509Certificate[] getAcceptedIssuers() {
			return null;
		}

		public boolean isServerTrusted(java.security.cert.X509Certificate[] certs) {
			return true;
		}

		public boolean isClientTrusted(java.security.cert.X509Certificate[] certs) {
			return true;
		}

		public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType)
				throws java.security.cert.CertificateException {
			return;
		}

		public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType)
				throws java.security.cert.CertificateException {
			return;
		}
	}

}
