/*********************************************************************
* All Rights reserved,Copyright (c) K-Opticom
**********************************************************************
*＜プログラム内容＞
*	システム名		：eo顧客基幹システム
*	モジュール名	：JKKCtrlTobilaInfo
*	ソースファイル名：JKKCtrlTobilaInfo.java
*	作成者			：FJ）中原
*	日付			：2020年06月15日
*＜機能概要＞
*	トビラシステムズ社 外部連携（本番環境用）コマンド発行部品です。
*＜修正履歴＞
*	バージョン	修正日		修正者		修正内容
*	v50.00.00	2020/06/15  FJ)中原		【ANK-3754-00-00】トビラフォン対応
*	v54.00.00	2021/09/03  FJ)中原		【OM-2021-0000856】トビラシステムとの接続異常対応
*
**********************************************************************/
package eo.common.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fujitsu.futurity.model.common.JCMAPLConstMgr;


/**
 *  トビラシステムズ連携独自処理部品（本番環境用）です。<p>
 * <br>
 * @author 富士通
 */
public class JKKCtrlTobilaInfoImpl extends JKKCtrlTobilaInfo
{
	
	/** 【HTTPヘッダ】  */
	/** CONTENT_TYPE  */
	private static final String CONTENT_TYPE = "Content-Type";

	/** CONTENT_TYPE_設定値  */
	private static final String CONTENT_TYPE_VALUE = "application/json";

	/** TOBILA文字コード */
	private static final String TOBILA_ENCODING = "UTF-8";

	// リクエストパラメータ定数定義
	/** HGW連携パラメータ */
	private static final String HGW_KEY = "hgw_key";

	/** 電話番号 */
	private static final String TEL_NUM = "tel_num";

	/** サービス開始日 */
	private static final String START_DATE = "start_date";

	/** 解約日 */
	private static final String CANCEL_DATE = "cancel_date";

	/** 機能初期利用フラグ */
	private static final String DEFAULT_ENABLED = "default_enabled";

	// レスポンスパラメータ定数定義
	/** エラーコード */
	private static final String ERROR_CODE = "error_code";

	/**
	 * トビラシステムズリトライ回数
	 */
	protected static final String KK_TOBILA_RETRYCOUNT = "KK_TOBILA_RETRYCOUNT";
	
	/**
	 * トビラシステムズ連携接続タイムアウト値
	 */
	protected static final String KK_TOBILA_CONNECT_TIMEOUT = "KK_TOBILA_CONNECT_TIMEOUT";
	
	/**
	 * トビラシステムズ連携読取タイムアウト値
	 */
	protected static final String KK_TOBILA_READ_TIMEOUT = "KK_TOBILA_READ_TIMEOUT";
	
	/**
	 * トビラシステムズ連携リトライインターベル値
	 */
	protected static final String KK_TOBILA_RETRYINTERVAL = "KK_TOBILA_RETRYINTERVAL";
	
	/**
	* 接続先URL(あんしん発着信サービス提供開始依頼)
	 */
	protected static final String KK_TOBILA_URL_KKIFE435 = "KK_TOBILA_URL_KKIFE435";
	
	/**
	* 接続先URL(あんしん発着信サービス解約依頼)
	 */
	protected static final String KK_TOBILA_URL_KKIFE442 = "KK_TOBILA_URL_KKIFE442";
	

	

	/**
	 *  トビラシステムズ連携処理を行います。
	 *  <br>
	 * @param serviceMap トビラシステムズ連携のインターフェイス情報
	 * @return 処理結果コード値　0：正常　1:異常
	 */
	public Map<String, Object> call_tobila(Map<String, Object> serviceMap) throws Exception
	{
		// 電文送信処理の実行
		HashMap<String, Object> result = execute(serviceMap);
		
		return result;
	}
	
	/**
	 * JSON電文送信処理を実行する。
	 * 
	 * @param serviceMap あんしん発着信サービス提供開始依頼・あんしん発着信サービス解約依頼のインターフェイス情報
	 * @return 処理結果コード値　0：正常　1:異常
	 * @throws Exception 
	 */
	private HashMap<String, Object>  execute(Map<String, Object>serviceMap) throws Exception 
	{
		// レスポンス
		HashMap<String, Object> result = new HashMap<String, Object>();
		// HTTPStatus
		int httpStatus = 500;
		IOException ex = null;
		String errCode = "";
		String reqLog = "";
		String resLog = "";
		
		int retryCount = Integer.parseInt(JCMAPLConstMgr.getString(KK_TOBILA_RETRYCOUNT));
		retryCount += 1;
		Integer retryInterval =(Integer.parseInt(JCMAPLConstMgr.getString(KK_TOBILA_RETRYINTERVAL) ));
		
		for(int i = 0 ; i < retryCount ; i++)
		{
			HttpURLConnection connection = null;
			URL url = null;
			String urlString = "";
			// レスポンス
			StringBuffer response = new StringBuffer();
			// OM-2021-0000856 ADD START
			ex = null;
			// OM-2021-0000856 ADD END
			
			try
			{
				// あんしん発着信サービス提供開始依頼のURL
				if ( serviceMap.containsKey("tajgsKeiIdoSbtCd") && "0301".equals(serviceMap.get("tajgsKeiIdoSbtCd")) )
				{
					 urlString = JCMAPLConstMgr.getString(KK_TOBILA_URL_KKIFE435);
				}
				// あんしん発着信サービス解約依頼のURL
				else
				{
					 urlString = JCMAPLConstMgr.getString(KK_TOBILA_URL_KKIFE442);
				}
				
				url = new URL(urlString);
				
			
				// 電文を送信
				// SSLの場合、HttpsURLConnectionへキャスト
				connection = (HttpURLConnection) url.openConnection();
				connection.setDoInput(true);
				connection.setDoOutput(true);
				
				// トビラシステムズ社との通信におけるタイムアウト値
				Integer tobilaConectTimeout =(Integer.parseInt(JCMAPLConstMgr.getString(KK_TOBILA_CONNECT_TIMEOUT) ));
				Integer tobilaReadTimeout =(Integer.parseInt(JCMAPLConstMgr.getString(KK_TOBILA_READ_TIMEOUT) ));
				connection.setConnectTimeout(tobilaConectTimeout);
				connection.setReadTimeout(tobilaReadTimeout);
				// HTTPリクエストコード
				connection.setRequestMethod("POST");
				// HTTPヘッダの設定
				connection.setRequestProperty(CONTENT_TYPE, CONTENT_TYPE_VALUE);
				
				// JSON形式の文字列を作成する。
				String json = requestParamMake(serviceMap);
				reqLog = json.replaceAll("\\s+", " ");
				
				OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream(), TOBILA_ENCODING);
				out.write(json);

				out.flush();
				
				// 接続
				connection.connect();
				
				httpStatus = connection.getResponseCode();

				InputStream in = null ;
				// 通信に成功したテキストを取得する
				if (httpStatus != HttpURLConnection.HTTP_OK)
				{
					in = connection.getErrorStream();
				}
				else
				{
					in = connection.getInputStream();
				}
				String encoding = connection.getContentEncoding();
				if (null == encoding)
				{
					encoding = TOBILA_ENCODING;
				}
				final InputStreamReader inReader = new InputStreamReader(in, encoding);
				final BufferedReader bufReader = new BufferedReader(inReader);
				String line = null;

				while ((line = bufReader.readLine()) != null)
				{
					response.append(line);
				}
				resLog = response.toString().replaceAll("\\s+", " ");
				bufReader.close();
				inReader.close();
				in.close();
				// 返却値が存在しない場合
				if ( response.length() > 0 )
				{
					ObjectMapper mapper = new ObjectMapper();
					JsonNode root = mapper.readTree(response.toString());
					// 【処理結果】を取得
					if (root.get(ERROR_CODE) != null)
					{
						errCode = root.get(ERROR_CODE).textValue();
					}
				}
			}
			catch (IOException e)
			{
				e.printStackTrace();
				ex = e;
			}
			finally
			{
				result.put("request", reqLog);
				result.put("response", resLog);
				if (connection != null)
				{
					//切断処理
					connection.disconnect();
					connection = null;
				}
			}
			// 失敗時はリトライ回数の上限までリトライ
			if (((ex != null) || (httpStatus != HttpURLConnection.HTTP_OK)) && (i < retryCount))
			{
				try
				{
					Thread.sleep(retryInterval);
				}
				catch (InterruptedException e)
				{
					// 割り込み要求による例外は無視
				}
				continue;
			}
			else
			{
				errCode = "";
				break;
			}
		}
		
		// 例外情報がある場合はthrowする
		if (ex != null)
		{
			throw ex;
		}
		result.put("httpStatusCd", httpStatus);
		result.put("errCode", errCode);
		
		
		return result;
	}
	
	
	
	/**
	 * TOBILA APIに対して送信するリクエストパラメータを作成する。
	 * @param Map<String, Object> 入力パラメータ
	 * @return TOBILA JSON形式のリクエストパラメータを返却する。
	 * @throws IOException JOSN形式へ変換する際のI/O例外
	 */
	private static String requestParamMake(Map<String, Object> serviceMap) throws IOException
	{

		// JOSN形式へ変換するためのMAP
		Map<String, Object> requestMap = new HashMap<String, Object>();
		// 変換後文字列
		String json = "";

		// リクエストパラメータ
		// HGW連携パラメータ
		requestMap.put(HGW_KEY, (String)serviceMap.get("tobilaphId"));

		// 電話番号
		requestMap.put(TEL_NUM, (String)serviceMap.get("telNo"));

		// 以下API毎の固有設定 START
		// サービス開始日
		if ( serviceMap.containsKey("startDate") )
		{
			requestMap.put(START_DATE, (String)serviceMap.get("startDate"));
		}

		// 解約日
		if ( serviceMap.containsKey("cancelDate") )
		{
			requestMap.put(CANCEL_DATE, (String)serviceMap.get("cancelDate"));
		}

		// 機能初期利用フラグ
		if ( serviceMap.containsKey("defaultEnabled") )
		{
			requestMap.put(DEFAULT_ENABLED, (String)serviceMap.get("defaultEnabled"));
		}
		// 以下API毎の固有設定 END

		ObjectMapper mapper = new ObjectMapper();
		mapper.enable(SerializationFeature.INDENT_OUTPUT);
		try
		{
			// JOSN形式へ変換
			json = mapper.writeValueAsString(requestMap);

		} catch (IOException e)
		{
			e.printStackTrace();
			throw e;
		}
		
		return json;
	}
}
