package com.yihu.wlyy.util;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;

import org.apache.commons.lang3.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.jdom.input.SAXBuilder;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;
import org.json.JSONArray;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SOAPUtil {

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

	private static String defaultUrl;
	private static String defaultNamespace;
	private static byte[] publicKey;
	private static byte[] bKEY;

	static {
		try {
			publicKey = RSAUtils.getPublicGovKey(); // 卫计委公钥
			defaultUrl = SystemConf.getInstance().getXMGuahaoUrl();
			defaultNamespace = SystemConf.getInstance().getXMGuahaoNamespace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}


	/**
	 * 文件内容替换
	 */
	private static String replace(String inFileName, JSONArray params) throws IOException {
		String xml = XmlToString(inFileName);
		if (params == null || params.length() == 0) {
			return xml;
		}
		for (int i = 0; i < params.length(); i++) {
			JSONObject json = params.getJSONObject(i);
			xml = xml.replace(json.getString("key"), json.getString("value"));
		}
		return xml;
	}
	private static org.jdom.Document load(String path) {
		org.jdom.Document document = null;
		try {
			SAXBuilder reader = new SAXBuilder();
			document = reader.build(new File(path));
		} catch (Exception e) {
			e.printStackTrace();
		}
		return document;
	}
	private static String XmlToString(String path) {
		org.jdom.Document document = load(path);

		Format format = Format.getPrettyFormat();
		format.setEncoding("UTF-8");// 设置编码格式

		StringWriter out = null; // 输出对象
		String sReturn = ""; // 输出字符串
		XMLOutputter outputter = new XMLOutputter();
		out = new StringWriter();
		try {
			outputter.output(document, out);
		} catch (IOException e) {
			e.printStackTrace();
		}
		sReturn = out.toString();
		return sReturn;
	}

	/**
	 * 获取soap消息主体
	 * @return
     */
	private static String getRequestBody(String fileName,JSONArray params) throws Exception
	{
		String xml = SOAPUtil.class.getClassLoader().getResource("soap/guaihao/" + fileName + ".xml").getFile();
		return replace(xml, params);
	}


	/**
	 * 从输入流中读取数据
	 * @param inStream
	 * @return
	 * @throws IOException
	 * @throws Exception
	 */
	private static byte[] readInputStream(InputStream inStream) throws IOException {
		ByteArrayOutputStream outStream = null;
		byte[] data = null;
		try {
			outStream = new ByteArrayOutputStream();
			byte[] buffer = new byte[1024];
			int len = 0;
			while ((len = inStream.read(buffer)) != -1) {
				outStream.write(buffer, 0, len);
			}
			data = outStream.toByteArray();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (outStream != null) {
				outStream.close();
			}
			if (inStream != null) {
				inStream.close();
			}
		}
		return data;
	}

	/**
	 * 获取身份证据
	 */
	private static String getStrCredential() {
		Document document = DocumentHelper.createDocument();
		Element root = document.addElement("root");
		root.addElement("org").addAttribute("code", "jkzl").addText("健康之路");
		root.addElement("visitor").addAttribute("type", "0").addAttribute("code", "jtqy").addAttribute("key", "jtqy").addText("健康之路");
		return document.asXML();// 身份证据
	}

	/**
	 * 将字符串转成unicode
	 * @param str 待转字符串
	 * @return unicode字符串
	 */
	private static String string2Unicode(String str) {
		str = (str == null ? "" : str);
		String tmp;
		StringBuffer sb = new StringBuffer(1000);
		char c;
		int i, j;
		sb.setLength(0);
		for (i = 0; i < str.length(); i++) {
			c = str.charAt(i);
			sb.append("\\u");
			j = (c >>> 8); // 取出高8位
			tmp = Integer.toHexString(j);
			if (tmp.length() == 1)
				sb.append("0");
			sb.append(tmp);
			j = (c & 0xFF); // 取出低8位
			tmp = Integer.toHexString(j);
			if (tmp.length() == 1)
				sb.append("0");
			sb.append(tmp);
		}
		return (new String(sb));
	}
	/******************************************************************************************/
	/**
	 * 使用默认服务地址
     */
	public static String post(String api, JSONArray params) throws Exception {

		return post(defaultUrl,defaultNamespace,api,params);
	}

	public static String post(String urlString,String namespace,String api,JSONArray params) throws Exception{
		String body = getRequestBody(api,params);
		return post(urlString,namespace,api,body);
	}

	/**
	 * webservice 调用接口
     */
	public static String post(String urlString,String namespace,String api, String body) throws Exception {
		OutputStream out = null;
		try {
			URL url = new URL(urlString);
			HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
			httpConn.setRequestProperty("Content-Length", String.valueOf(body.length()));
			httpConn.setRequestProperty("Content-Type", "text/xml; charset=utf-8");
			httpConn.setRequestProperty("soapActionString", namespace + api);
			httpConn.setRequestMethod("POST");
			httpConn.setDoOutput(true);
			httpConn.setDoInput(true);
			out = httpConn.getOutputStream();
			out.write(body.getBytes());

			byte[] datas = readInputStream(httpConn.getInputStream());
			String result = new String(datas, "UTF-8");
			Document document = DocumentHelper.parseText(result);
			Element rootElement = document.getRootElement();
			Element bodyElement = rootElement.element("Body");
			Element responseElement = bodyElement.element(api + "Response");
			Element resultElement = responseElement.element(api + "Result");
			return resultElement.getText();
		} catch (Exception e) {
			logger.error("SOAPUtil post error:", e);
			throw new Exception("当前的网络情况较差，请稍候重试");
		} finally {
			if (out != null) {
				out.close();
				out.flush();
			}
		}
	}

	/**
	 * 对称加密后结果
	 */
	public static String[] getCredential(String strCondition, boolean credential) throws UnsupportedEncodingException {
		String strCredential = null;
		String condition = null;
		String strKey = null;
		// 生成临时对称密钥bKEY
		if (bKEY == null) {
			bKEY = sehrCrypto.sehrCrypto.GenerateKey128();
		}
		if (credential) {
			// 对身份证据Compress()压缩
			byte[] bSource = getStrCredential().getBytes("UTF-16LE");
			byte[] pbyteSource = sehrCrypto.sehrCrypto.Compress(bSource);
			// 采用bKEY对称加密Encrypt()
			byte[] encryptSource = sehrCrypto.sehrCrypto.Encrypt(pbyteSource, bKEY);
			// 再编码EncodeU()
			strCredential = new String(sehrCrypto.sehrCrypto.EncodeU(encryptSource));
		}
		if (StringUtils.isNotEmpty(strCondition)) {
			// 对身份证据Compress()压缩
			byte[] pbyteSource = sehrCrypto.sehrCrypto.Compress(strCondition.getBytes("UTF-16LE"));
			// 采用bKEY对称加密Encrypt()
			byte[] encryptSource = sehrCrypto.sehrCrypto.Encrypt(pbyteSource, bKEY);
			// 再编码EncodeU()
			condition = new String(sehrCrypto.sehrCrypto.EncodeU(encryptSource));
		}
		byte[] bKeyRsa = sehrCrypto.sehrCrypto.RSAEncrypt(bKEY, publicKey);
		strKey = new String(sehrCrypto.sehrCrypto.EncodeU(bKeyRsa));

		return new String[] { condition, strCredential, strKey };
	}


}
