/*********************************************************************
 * All Rights reserved,Copyright (c) K-Opticom
 **********************************************************************
 *＜プログラム内容＞
 *   システム名      ：eo顧客基幹システム
 *   モジュール名    ：JFUSocialGoogleInterface
 *   ソースファイル名：JFUSocialGoogleInterface.java
 *   作成者          ：富士通
 *   日付            ：2021年04月08日
 *＜機能概要＞
 *   ソーシャルID認証（Google）の外部APIを呼び出すIF部品です。
 *＜修正履歴＞
 *   バージョン  修正日       修正者      修正内容
 *   v53.00      2021/04/08   FJ）張本    【ANK-4009-00-00】CX戦略WG方針対応
 *
 **********************************************************************/
package eo.web.webview.common;

import static com.fujitsu.futurity.web.x31.X31SWebLog.DEBUG_LOG;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.net.HttpURLConnection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import java.util.Map.Entry;

import org.json.JSONObject;

import com.fujitsu.futurity.web.x31.X31SWebLog;

import eo.common.constant.JFUStrConst;

/**
 * ソーシャルID認証（Yahoo）の外部APIを呼び出すIF部品です。
 *
 * <br>
 * @author 富士通
 * @see JFUUrlConnection フロント用HTTP又はSSLリクエストの送信部品
 */
public class JFUSocialYahooInterface extends JFUUrlConnection
{
	/** ソーシャルID認証 クライアントID **/
	public static final String CLIENT_ID = "client_id";
	/** ソーシャルID認証 リダイレクトURI **/
	public static final String REDIRECT_URI = "redirect_uri";
	/** ソーシャルID認証 レスポンスタイプ **/
	public static final String RESPONSE_TYPE = "response_type";
	/** ソーシャルID認証 バイル **/
	public static final String BAIL = "bail";
	/** ソーシャルID認証 スコープ **/
	public static final String SCOPE = "scope";
	/** ソーシャルID認証 ステート **/
	public static final String STATE = "state";
	/** ソーシャルID認証 ナンス **/
	public static final String NONCE = "nonce";
	/** ソーシャルID認証 アクセスタイプ **/
	public static final String ACCESS_TYPE = "access_type";
	/** ソーシャルID認証 ディスプレイ **/
	public static final String DISPLAY = "display";
	/** ソーシャルID認証 プロンプト **/
	public static final String PROMPT = "prompt";
	/** ソーシャルID認証 最大認証経過時間 **/
	public static final String MAX_AGE = "max_age";
	/** ソーシャルID認証 認可コード **/
	public static final String CODE = "code";
	/** ソーシャルID認証 セキュリティトークン **/
	public static final String SECURITY_TOKEN = "security_token";

	/** ソーシャルIDアクセストークン取得 クライアントシークレット **/
	public static final String CLIENT_SECRET = "client_secret";
	/** ソーシャルIDアクセストークン取得 付与タイプ **/
	public static final String GRANT_TYPE = "grant_type";
	/** ソーシャルIDアクセストークン取得 アクセストークン **/
	public static final String ACCESS_TOKEN = "access_token";
	/** ソーシャルIDアクセストークン取得 トークンタイプ **/
	public static final String TOKEN_TYPE = "token_type";
	/** ソーシャルIDアクセストークン取得 リフレッシュトークン **/
	public static final String REFRESH_TOKEN = "refresh_token";
	/** ソーシャルIDアクセストークン取得 アクセストークン有効期間 **/
	public static final String EXPIRES_IN = "expires_in";
	/** ソーシャルIDアクセストークン取得 IDトークン **/
	public static final String ID_TOKEN = "id_token";

	/** ソーシャルIDアクセストークン取得 IDトークン IDトークン発行元 **/
	public static final String IT_ISS = "iss";
	/** ソーシャルIDアクセストークン取得 IDトークン ユーザー識別子 **/
	public static final String IT_SUB = "sub";
	/** ソーシャルIDアクセストークン取得 IDトークン クライアントID配列 **/
	public static final String IT_AUD = "aud";
	/** ソーシャルIDアクセストークン取得 IDトークン IDトークン有効期限 **/
	public static final String IT_EXP = "exp";
	/** ソーシャルIDアクセストークン取得 IDトークン IDトークン発行時刻 **/
	public static final String IT_IAT = "iat";
	/** ソーシャルIDアクセストークン取得 IDトークン 認証時刻 **/
	public static final String IT_AUTH_TIME = "auth_time";
	/** ソーシャルIDアクセストークン取得 IDトークン ナンス **/
	public static final String IT_NONCE = "nonce";
	/** ソーシャルIDアクセストークン取得 IDトークン 認証手段 **/
	public static final String IT_AMR = "amr";
	/** ソーシャルIDアクセストークン取得 IDトークン アクセストークンハッシュ値 **/
	public static final String IT_AT_HASH = "at_hash";
	/** ソーシャルIDアクセストークン取得 IDトークン コードハッシュ値 **/
	public static final String IT_C_HASH = "c_hash";

	/** ソーシャルIDユーザ情報取得 コールバック **/
	public static final String CALLBACK = "callback";
	/** ソーシャルIDユーザ情報取得 ユーザー識別子 **/
	public static final String SUB = "sub";
	/** ソーシャルIDユーザ情報取得 姓名 **/
	public static final String NAME = "name";
	/** ソーシャルIDユーザ情報取得 姓 **/
	public static final String FAMILY_NAME = "family_name";
	/** ソーシャルIDユーザ情報取得 カナ姓 **/
	public static final String FAMILY_NAME_JA_KANA_JP = "family_name#ja-Kana-JP";
	/** ソーシャルIDユーザ情報取得 漢字姓 **/
	public static final String FAMILY_NAME_JA_HANI_JP = "family_name#ja-Hani-JP";
	/** ソーシャルIDユーザ情報取得 名 **/
	public static final String GIVEN_NAME = "given_name";
	/** ソーシャルIDユーザ情報取得 カナ名 **/
	public static final String GIVEN_NAME_JA_KANA_JP = "given_name#ja-Kana-JP";
	/** ソーシャルIDユーザ情報取得 漢字名 **/
	public static final String GIVEN_NAME_JA_HANI_JP = "given_name#ja-Hani-JP";
	/** ソーシャルIDユーザ情報取得 性別 **/
	public static final String GENDER = "gender";
	/** ソーシャルIDユーザ情報取得 ゾーン情報 **/
	public static final String ZONEINFO = "zoneinfo";
	/** ソーシャルIDユーザ情報取得 ロケール **/
	public static final String LOCALE = "locale";
	/** ソーシャルIDユーザ情報取得 生年 **/
	public static final String BIRTHDATE = "birthdate";
	/** ソーシャルIDユーザ情報取得 ニックネーム **/
	public static final String NICKNAME = "nickname";
	/** ソーシャルIDユーザ情報取得 プロフィール画像 **/
	public static final String PICTURE = "picture";
	/** ソーシャルIDユーザ情報取得 メールアドレス **/
	public static final String EMAIL = "email";

	/** ソーシャルID認証 クライアントID値 取得キー */
	public static final String KEY_API_YAHOO_CLIENT_ID = "API_YAHOO_CLIENT_ID";
	/** ソーシャルID認証 クライアントシークレット値 取得キー */
	public static final String KEY_API_YAHOO_CLIENT_SECRET = "API_YAHOO_CLIENT_SECRET";
	/** ソーシャルID認証 リダイレクトU得キー */
	public static final String KEY_API_YAHOO_REDIRECT_URI = "API_YAHOO_REDIRECT_URI";
	/** ソーシャルID認証 レスポンスタイプ値 取得キー */
	public static final String KEY_API_YAHOO_RESPONSE_TYPE = "API_YAHOO_RESPONSE_TYPE";
	/** ソーシャルID認証 バイル値 取得キー */
	public static final String KEY_API_YAHOO_BAIL = "API_YAHOO_BAIL";
	/** ソーシャルID認証 スコープ値 取得キー */
	public static final String KEY_API_YAHOO_SCOPE = "API_YAHOO_SCOPE";
	/** ソーシャルID認証 アクセスタイプ値 取得キー */
	public static final String KEY_API_YAHOO_ACCESS_TYPE = "API_YAHOO_ACCESS_TYPE";
	/** ソーシャルID認証 ディスプレイ値 取得キー */
	public static final String KEY_API_YAHOO_DISPLAY = "API_YAHOO_DISPLAY";
	/** ソーシャルID認証 プロンプト値 取得キー */
	public static final String KEY_API_YAHOO_PROMPT = "API_YAHOO_PROMPT";
	/** ソーシャルID認証 最大認証経過時間値 取得キー */
	public static final String KEY_API_YAHOO_MAX_AGE = "API_YAHOO_MAX_AGE";
	/** ソーシャルID認証 付与タイプ値 取得キー */
	public static final String KEY_API_YAHOO_GRANT_TYPE = "API_YAHOO_GRANT_TYPE";

	/** ソーシャルIDアクセストークン取得（Yahoo）API タイムアウト値取得キー */
	private static final String STATUS_TIMEOUT = "API_YAHOO_STATUS_TIMEOUT";
	/** ソーシャルIDアクセストークン取得（Yahoo）API 文字コード取得キー */
	private static final String STATUS_CHARCODE = "API_YAHOO_STATUS_CHARCODE";

	/** 性別：male */
	public static final String GENDER_MALE = "male";
	/** 性別：female */
	public static final String GENDER_FEMALE = "female";

	/**
	 * ソーシャルIDアクセストークン取得APIを実施します。
	 *
	 * <br>
	 * @param code 認可コード
	 * @return 処理結果
	 */
	public static HashMap<String, Object> getSocialIdTokenReqRslt(String code)
	{
		HashMap<String, String> inMap = new HashMap<String, String>();

		String clientId = JCCWebCommon.getApplicationConst(KEY_API_YAHOO_CLIENT_ID);
		String clientSecret = JCCWebCommon.getApplicationConst(KEY_API_YAHOO_CLIENT_SECRET);
		String redirectUri = JCCWebCommon.getApplicationConst(KEY_API_YAHOO_REDIRECT_URI);
		String grantType = JCCWebCommon.getApplicationConst(KEY_API_YAHOO_GRANT_TYPE);

		inMap.put(CLIENT_ID, clientId);
		inMap.put(CLIENT_SECRET, clientSecret);
		inMap.put(REDIRECT_URI, redirectUri);
		inMap.put(CODE, code);
		inMap.put(GRANT_TYPE, grantType);

		X31SWebLog.DEBUG_LOG.debug("【開始】ソーシャルIDアクセストークン取得（Yahoo）API");
		X31SWebLog.DEBUG_LOG.debug("FUIFE187(Req) :" + inMap);
		HashMap<String, Object> result = execute(inMap, KEY_YAHOO_GET_TOKEN_URL);
		X31SWebLog.DEBUG_LOG.debug("FUIFE187(Res) :" + result);
		X31SWebLog.DEBUG_LOG.debug("【終了】ソーシャルIDアクセストークン取得（Yahoo）API");
		return result;
	}

	/**
	 * ソーシャルIDユーザ情報取得APIを実施します。
	 *
	 * <br>
	 * @param accessToken アクセストークン
	 * @return 処理結果
	 */
	public static HashMap<String, Object> getSocialIdUserInfoReqRslt(String accessToken)
	{
		HashMap<String, String> inMap = new HashMap<String, String>();
		inMap.put(ACCESS_TOKEN, accessToken);
		inMap.put(CALLBACK, "");

		X31SWebLog.DEBUG_LOG.debug("【開始】ソーシャルIDユーザ情報取得（Yahoo）API");
		X31SWebLog.DEBUG_LOG.debug("FUIFE188(Req) :" + inMap);
		HashMap<String, Object> result = execute(inMap, KEY_YAHOO_GET_USER_URL);
		X31SWebLog.DEBUG_LOG.debug("FUIFE188(Res) :" + result);
		X31SWebLog.DEBUG_LOG.debug("【終了】ソーシャルIDユーザ情報取得（Yahoo）API");
		return result;
	}

	/**
	 * ソーシャルIDアクセストークン取得／ユーザ情報取得（Yahoo）APIを呼び出します。
	 *
	 * <br>
	 * @param inMap 送信情報
	 * @param urlKey 外部APIのURLキー
	 * @return 処理結果
	 */
	private static HashMap<String, Object> execute(HashMap<String, String> inMap, String urlKey)
	{
		HashMap<String, Object> result = null;

		// 正常時
		result = connect(inMap, urlKey);
		//		if (result.length() > 3 && VERIFY_RESULT_SUCCESS.equals(result.substring(0, 4)))
		//		{
		//			result = VERIFY_RESULT_SUCCESS;
		//		}
		return result;
	}

	/**
	 * ソーシャルIDアクセストークン取得／ユーザ情報取得（Yahoo）APIの呼び出し
	 * 
	 * @param inMap リクエスト情報
	 * @param urlKey URLキー
	 * @return レスポンス情報
	 */
	@SuppressWarnings("unchecked")
	private static HashMap<String, Object> connect(HashMap<String, String> inMap, String urlKey)
	{
		X31SWebLog.DEBUG_LOG.debug("【開始】ソーシャルIDアクセストークン取得／ユーザ情報取得（Yahoo）API 接続処理(connect)");

		HttpURLConnection conn = null;
		HashMap<String, Object> resMap = new HashMap<String, Object>();
		int statusCode = 999;
		try
		{
			// リクエストタイムアウト値
			int timeOut = Integer.parseInt(JCCWebCommon.getApplicationConst(STATUS_TIMEOUT));
			// HTTPリクエストエンコード
			String encoding = JCCWebCommon.getApplicationConst(STATUS_CHARCODE);
			conn = createConnection(urlKey, timeOut);

			X31SWebLog.DEBUG_LOG.debug("【処理中】ソーシャルIDアクセストークン取得／ユーザ情報取得（Yahoo）：URL：" + conn.getURL());
			X31SWebLog.DEBUG_LOG.debug("【処理中】ソーシャルIDアクセストークン取得／ユーザ情報取得（Yahoo）：文字コード：" + encoding);
			X31SWebLog.DEBUG_LOG.debug("【処理中】ソーシャルIDアクセストークン取得／ユーザ情報取得（Yahoo）：タイムアウト：" + 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("【処理中】ソーシャルIDアクセストークン取得／ユーザ情報取得（Yahoo）：" + 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("【処理中】ソーシャルIDアクセストークン取得／ユーザ情報取得（Yahoo）：HTTPステータス：" + statusCode);

			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)
				{
					X31SWebLog.DEBUG_LOG.debug("【処理中】ソーシャルIDアクセストークン取得／ユーザ情報取得（Yahoo）：例外発生：" + e);
				}
				finally
				{
					if (null != bos)
					{
						bos.close();
					}
					if (null != bis)
					{
						bis.close();
					}
				}

				if (outputByte != null)
				{
					String res = new String(outputByte, encoding);

					JSONObject rceiveObject = new JSONObject(res);
					DEBUG_LOG.info("DEBUG：ソーシャルID取得処理 out項目=" + rceiveObject.toString());

					for (Iterator<String> iterator = rceiveObject.keys(); iterator.hasNext();)
					{
						String key = iterator.next();
						resMap.put(key, rceiveObject.get(key));
					}
				}
			}
		}
		catch (Exception e)
		{
			X31SWebLog.DEBUG_LOG.debug("【処理中】ソーシャルIDアクセストークン取得／ユーザ情報取得（Yahoo）：例外発生：" + e);
		}
		finally
		{
			if (null != conn)
			{
				conn.disconnect();
			}
		}
		X31SWebLog.DEBUG_LOG.debug("【処理中】ソーシャルIDアクセストークン取得／ユーザ情報取得（Yahoo）：外部APIからのレスポンス：" + resMap.toString());
		X31SWebLog.DEBUG_LOG.debug("【終了】ソーシャルIDアクセストークン取得／ユーザ情報取得（Yahoo）API 接続処理(connect)");
		return resMap;
	}
}