/*********************************************************************
 * All Rights reserved,Copyright (c) K-Opticom
 **********************************************************************
 *＜プログラム内容＞
 *   システム名      ：eo顧客基幹システム
 *   モジュール名    ：JFUCapyInterface
 *   ソースファイル名：JFUCapyInterface.java
 *   作成者          ：富士通
 *   日付            ：2018年09月12日
 *＜機能概要＞
 *   Capy稼動監視／回答照会APIを呼び出すIF部品です。
 *＜修正履歴＞
 *   バージョン  修正日       修正者      修正内容
 *   v38.00.00    2018/09/12   FJ）西川    新規作成
 *
 **********************************************************************/
package eo.web.webview.common;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import java.util.Map.Entry;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.xpath.XPathExpressionException;

import org.xml.sax.SAXException;

import com.fujitsu.futurity.common.JSYLogBase;
import com.fujitsu.futurity.common.JSYwebLog;
import com.fujitsu.futurity.web.x31.X31BWebBusinessLogic;
import com.fujitsu.futurity.web.x31.X31SWebLog;

import eo.common.constant.JFUStrConst;

/**
 * Capy稼動監視／回答照会APIを呼び出すIF部品です。
 *
 * <br>
 * @author 富士通
 * @see JFUUrlConnection フロント用HTTP又はSSLリクエストの送信部品
 */
public class JFUCapyInterface extends JFUUrlConnection
{

	/** Capy稼動監視API タイムアウト値取得キー */
	private static final String STATUS_TIMEOUT = "API_CAPY_STATUS_TIMEOUT";

	/** Capy稼動監視API 文字コード取得キー */
	private static final String STATUS_CHARCODE = "API_CAPY_STATUS_CHARCODE";

	/** Capy稼動監視API 正常終了 */
	public static final String STATUS_RESULT_SUCCESS = "operational";

	/** Capy回答照会API タイムアウト値取得キー */
	private static final String VERIFY_TIMEOUT = "API_CAPY_VERIFY_TIMEOUT";

	/** Capy回答照会API 文字コード取得キー */
	private static final String VERIFY_CHARCODE = "API_CAPY_VERIFY_CHARCODE";

	/** Capy回答照会API リクエスト プライベートキー */
	private static final String VERIFY_REQ_PRIVATEKEY = "capy_privatekey";

	/** Capy回答照会API リクエスト チャレンジキー */
	public static final String VERIFY_REQ_CHALLENGEKEY = "capy_challengekey";

	/** Capy回答照会API リクエスト 回答 */
	public static final String VERIFY_REQ_ANSWER = "capy_answer";

	/** Capy回答照会API リクエスト プライベートキー */
	private static final String VERIFY_PRIVATEKEY = "CAPY_PRIVATEKEY";

	/** Capy回答照会API 正常終了 */
	public static final String VERIFY_RESULT_SUCCESS = "true";

	/** Capy稼動監視API／回答照会API 結果 パラメータ必須チェックエラー */
	private static final String ERROR_PARAMETER = "888";

	/** Capy稼動監視API／回答照会API 結果 システムエラー */
	private static final String ERROR_SYSTEM = "999";

	/**
	 * 稼動監視APIを実施します。
	 *
	 * <br>
	 * @param bl 画面オブジェクト
	 * @param eoid eoID
	 * @return 処理結果
	 * @throws ParserConfigurationException
	 * @throws SAXException
	 * @throws IOException
	 * @throws TransformerException
	 * @throws InterruptedException
	 * @throws NoSuchAlgorithmException
	 * @throws KeyManagementException
	 * @throws XPathExpressionException
	 */
	public static String getCapyStatusReqRslt(X31BWebBusinessLogic bl, String eoid) throws ParserConfigurationException, SAXException, IOException,
			TransformerException, InterruptedException, KeyManagementException, NoSuchAlgorithmException, XPathExpressionException
	{
		X31SWebLog.DEBUG_LOG.debug("【開始】Capy稼動監視API");
		String result = execute(null, KEY_CAPY_STATUS_URL, bl, eoid);
		X31SWebLog.DEBUG_LOG.debug("【終了】Capy稼動監視API");
		return result;
	}

	/**
	 * 稼動監視APIを実施します。
	 *
	 * <br>
	 * @param inMap 送信情報
	 * @param bl 画面オブジェクト
	 * @param eoid eoID
	 * @return 処理結果
	 * @throws ParserConfigurationException
	 * @throws SAXException
	 * @throws IOException
	 * @throws TransformerException
	 * @throws InterruptedException
	 * @throws NoSuchAlgorithmException
	 * @throws KeyManagementException
	 * @throws XPathExpressionException
	 */
	public static String getCapyVerifyReqRslt(HashMap<String, String> inMap, X31BWebBusinessLogic bl, String eoid)
			throws ParserConfigurationException, SAXException, IOException, TransformerException, InterruptedException, KeyManagementException,
			NoSuchAlgorithmException, XPathExpressionException
	{
		X31SWebLog.DEBUG_LOG.debug("【開始】Capy回答照会API");
		String result = execute(inMap, KEY_CAPY_VERIFY_URL, bl, eoid);
		X31SWebLog.DEBUG_LOG.debug("【終了】Capy回答照会API");
		return result;
	}

	/**
	 * Capy稼動監視／回答照会APIを呼び出します。
	 *
	 * <br>
	 * @param inMap 送信情報
	 * @param urlKey 外部APIのURLキー
	 * @param bl 画面オブジェクト
	 * @param eoid eoID
	 * @return 処理結果
	 * @throws ParserConfigurationException
	 * @throws SAXException
	 * @throws IOException
	 * @throws TransformerException
	 * @throws InterruptedException
	 * @throws NoSuchAlgorithmException
	 * @throws KeyManagementException
	 * @throws XPathExpressionException
	 */
	private static String execute(HashMap<String, String> inMap, String urlKey, X31BWebBusinessLogic bl, String eoid)
			throws ParserConfigurationException, SAXException, IOException, TransformerException, InterruptedException, KeyManagementException,
			NoSuchAlgorithmException, XPathExpressionException
	{
		String result = ERROR_SYSTEM;
		eoid = JFUWebCommon.nvl(eoid, "");

		if (KEY_CAPY_STATUS_URL.equals(urlKey))
		{

			outputBusLog("Capy稼動監視【開始】：eoID=" + eoid, bl.getClass());

			// HTTPリクエスト(GET) 接続実行
			result = connect(KEY_CAPY_STATUS_URL, bl, eoid).trim();
			outputBusLog("Capy稼動監視【終了】：eoID=" + eoid + "：ステータス=" + result, bl.getClass());
			if (STATUS_RESULT_SUCCESS.equals(result))
			{
				result = STATUS_RESULT_SUCCESS;
			}

		}
		else if (KEY_CAPY_VERIFY_URL.equals(urlKey))
		{
			String capyPrivatekey = JCCWebCommon.getApplicationConst(VERIFY_PRIVATEKEY);

			inMap.put(VERIFY_REQ_PRIVATEKEY, capyPrivatekey);

			outputBusLog("Capy回答照会【開始】：eoID=" + eoid, bl.getClass());

			// パラメータチェック
			if (isErrorParameter(inMap))
			{
				// 異常時

				result = ERROR_PARAMETER;
				outputBusLog("Capy回答照会【終了】：eoID=" + eoid + "：ステータス=" + result, bl.getClass());
			}
			else
			{
				// 正常時
				result = connect(inMap, urlKey, bl, eoid).trim();
				outputBusLog("Capy回答照会【終了】：eoID=" + eoid + "：ステータス=" + result, bl.getClass());
				if (result.length() > 3 && VERIFY_RESULT_SUCCESS.equals(result.substring(0, 4)))
				{
					result = VERIFY_RESULT_SUCCESS;
				}
			}
		}
		return result;
	}

	/**
	 * パラメータ必須チェックする。
	 *
	 * <br>
	 * @param inMap 送信情報
	 * @return true:パラメターエラーの場合、false:正常の場合
	 */
	private static boolean isErrorParameter(HashMap<String, String> inMap)
	{

		// プライベートキー
		if (!inMap.containsKey(VERIFY_REQ_PRIVATEKEY) || JFUWebCommon.isNull(inMap.get(VERIFY_REQ_PRIVATEKEY)))
		{
			X31SWebLog.DEBUG_LOG.debug("【処理中】Capy回答照会：パラメータ必須チェック：「プライベートキー」項目値が未設定");

			return true;
		}

		// チャレンジキー
		if (!inMap.containsKey(VERIFY_REQ_CHALLENGEKEY) || JFUWebCommon.isNull(inMap.get(VERIFY_REQ_CHALLENGEKEY)))
		{
			X31SWebLog.DEBUG_LOG.debug("【処理中】Capy回答照会：パラメータ必須チェック：「チャレンジキー」項目値が未設定");

			return true;
		}

		// 回答
		if (!inMap.containsKey(VERIFY_REQ_ANSWER) || JFUWebCommon.isNull(inMap.get(VERIFY_REQ_ANSWER)))
		{
			X31SWebLog.DEBUG_LOG.debug("【処理中】Capy回答照会：パラメータ必須チェック：「回答」項目値が未設定");

			return true;
		}
		return false;
	}

	/**
	 * Capy稼動監視APIの呼び出し
	 * 
	 * @param reqCapyMap リクエスト情報
	 * @param urlKey URLキー
	 * @return XML情報
	 * @throws KeyManagementException
	 * @throws NoSuchAlgorithmException
	 * @throws IOException
	 * @throws ParserConfigurationException
	 * @throws SAXException
	 */
	private static String connect(String urlKey, X31BWebBusinessLogic bl, String eoid)
	{
		X31SWebLog.DEBUG_LOG.debug("【開始】Capy稼動監視API 接続処理(connect)");

		HttpURLConnection conn = null;
		String res = JFUStrConst.EMPTY;
		int statusCode = 999;

		try
		{
			// リクエストタイムアウト値
			int timeOut = Integer.parseInt(JCCWebCommon.getApplicationConst(STATUS_TIMEOUT));
			conn = createConnection(urlKey, getTimeOut(STATUS_TIMEOUT));

			// HTTPリクエストエンコード
			String encoding = JCCWebCommon.getApplicationConst(STATUS_CHARCODE);

			X31SWebLog.DEBUG_LOG.debug("【処理中】Capy稼動監視：URL：" + conn.getURL());
			X31SWebLog.DEBUG_LOG.debug("【処理中】Capy稼動監視：文字コード：" + encoding);
			X31SWebLog.DEBUG_LOG.debug("【処理中】Capy稼動監視：タイムアウト：" + timeOut);

			// 接続
			conn.connect();

			statusCode = conn.getResponseCode();

			X31SWebLog.DEBUG_LOG.debug("【処理中】Capy稼動監視：HTTPステータス：" + statusCode);
			outputBusLog("Capy稼動監視【処理中】：eoID=" + eoid + "：HTTPステータス=" + statusCode, bl.getClass());

			if (statusCode == 200)
			{
				BufferedInputStream bis = null;
				ByteArrayOutputStream bos = null;
				byte[] outputByte = null;
				try
				{
					bis = new BufferedInputStream(conn.getInputStream());
					// レスポンスを読込み
					bos = new ByteArrayOutputStream();
					int intByte = 0;
					while (true)
					{
						intByte = bis.read();
						if (-1 == intByte)
						{
							break;
						}
						bos.write(intByte);
					}
					outputByte = bos.toByteArray();
				}
				catch (Exception e)
				{
					outputBusLog("Capy稼動監視【例外エラー】：eoID=" + eoid + "：HTTPステータス=" + statusCode, bl.getClass());
					X31SWebLog.DEBUG_LOG.debug("【処理中】Capy稼動監視：例外発生：" + e);
				}
				finally
				{
					if (null != bos)
					{
						bos.close();
					}
					if (null != bis)
					{
						bis.close();
					}
				}

				if (outputByte != null)
				{
					res = new String(outputByte, encoding);
				}
			}
		}
		catch (Exception e)
		{
			outputBusLog("Capy稼動監視【例外エラー】：eoID=" + eoid + "：HTTPステータス=" + statusCode, bl.getClass());
			X31SWebLog.DEBUG_LOG.debug("【処理中】Capy稼動監視：例外発生：" + e);
		}
		finally
		{
			if (null != conn)
			{
				conn.disconnect();
			}
		}
		X31SWebLog.DEBUG_LOG.debug("【処理中】Capy稼動監視：外部APIからのレスポンス：" + res);
		X31SWebLog.DEBUG_LOG.debug("【終了】Capy稼動監視API 接続処理(connect)");
		return res;
	}

	/**
	 * Capy回答照会APIの呼び出し
	 * 
	 * @param reqCapyMap リクエスト情報
	 * @param urlKey URLキー
	 * @return XML情報
	 * @throws KeyManagementException
	 * @throws NoSuchAlgorithmException
	 * @throws IOException
	 * @throws ParserConfigurationException
	 * @throws SAXException
	 */
	private static String connect(HashMap<String, String> inMap, String urlKey, X31BWebBusinessLogic bl, String eoid)
	{
		X31SWebLog.DEBUG_LOG.debug("【開始】Capy回答照会API 接続処理(connect)");

		HttpURLConnection conn = null;
		String res = JFUStrConst.EMPTY;
		int statusCode = 999;
		try
		{
			// リクエストタイムアウト値
			int timeOut = Integer.parseInt(JCCWebCommon.getApplicationConst(VERIFY_TIMEOUT));
			// HTTPリクエストエンコード
			String encoding = JCCWebCommon.getApplicationConst(VERIFY_CHARCODE);
			conn = createConnection(urlKey, timeOut);

			X31SWebLog.DEBUG_LOG.debug("【処理中】Capy回答照会：URL：" + conn.getURL());
			X31SWebLog.DEBUG_LOG.debug("【処理中】Capy回答照会：文字コード：" + encoding);
			X31SWebLog.DEBUG_LOG.debug("【処理中】Capy回答照会：タイムアウト：" + timeOut);

			Set<Entry<String, String>> resSet = inMap.entrySet();
			StringBuffer sb = new StringBuffer();

			int i = 0;
			for (Iterator<Entry<String, String>> iterator = resSet.iterator(); iterator.hasNext();)
			{
				sb.append(i == 0 ? JFUStrConst.EMPTY : JFUStrConst.HALF_AMPERSAND);
				Entry<String, String> entry = iterator.next();
				X31SWebLog.DEBUG_LOG.debug("【処理中】Capy回答照会：" + entry.getKey() + JFUStrConst.HALF_COLON + entry.getValue());
				sb.append(entry.getKey()).append(EQUAL_SIGN).append(entry.getValue());
				i++;
			}
			String param = sb.toString();
			conn = connection(conn, param, encoding);

			statusCode = conn.getResponseCode();

			X31SWebLog.DEBUG_LOG.debug("【処理中】Capy回答照会：HTTPステータス：" + statusCode);
			outputBusLog("Capy回答照会【処理中】：eoID=" + eoid + "：HTTPステータス=" + statusCode, bl.getClass());

			if (statusCode == 200)
			{

				BufferedInputStream bis = null;
				ByteArrayOutputStream bos = null;
				byte[] outputByte = null;
				try
				{
					bis = new BufferedInputStream(conn.getInputStream());
					// レスポンスを読込み
					bos = new ByteArrayOutputStream();
					int intByte = 0;
					while (true)
					{
						intByte = bis.read();
						if (-1 == intByte)
						{
							break;
						}
						bos.write(intByte);
					}
					outputByte = bos.toByteArray();
				}
				catch (Exception e)
				{
					outputBusLog("Capy回答照会【例外エラー】：eoID=" + eoid + "：HTTPステータス=" + statusCode, bl.getClass());

					X31SWebLog.DEBUG_LOG.debug("【処理中】Capy回答照会：例外発生：" + e);
				}
				finally
				{
					if (null != bos)
					{
						bos.close();
					}
					if (null != bis)
					{
						bis.close();
					}
				}

				if (outputByte != null)
				{
					res = new String(outputByte, encoding);
				}
			}
		}
		catch (Exception e)
		{
			outputBusLog("Capy回答照会【例外エラー】：eoID=" + eoid + "：HTTPステータス=" + statusCode, bl.getClass());
			X31SWebLog.DEBUG_LOG.debug("【処理中】Capy回答照会：例外発生：" + e);
		}
		finally
		{
			if (null != conn)
			{
				conn.disconnect();
			}
		}
		X31SWebLog.DEBUG_LOG.debug("【処理中】Capy回答照会：外部APIからのレスポンス：" + res);
		X31SWebLog.DEBUG_LOG.debug("【終了】Capy回答照会API 接続処理(connect)");
		return res;
	}

	/**
	 * ビジネスログへの出力処理
	 *
	 * @param msg ログ情報
	 * @param cls クラス
	 */
	@SuppressWarnings("unchecked")
	public static void outputBusLog(String msg, Class cls)
	{
		JSYwebLog.println(JSYLogBase.EXECUTION, cls, msg, "CS0003I", null, null);
	}
}