/*******************************************************************************
 *	All Rights reserved,Copyright (c) K-Opticom
 ********************************************************************************
 *＜プログラム内容＞
 *	システム名		：eo顧客基幹システム
 *	モジュール名	：CRW10501SFLogic
 *	ソースファイル名：CRW10501SFLogic.java
 *	作成者			：富士通
 *	日付			：2012年03月31日
 *＜機能概要＞
 *	OPMSログインビューロジック
 *＜修正履歴＞
 *	バージョン	修正日		修正者		修正内容
 *	ｖ3.00.00
 *
 ********************************************************************************/

package eo.web.webview.CRW10501SF;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.EventObject;
import java.util.HashMap;
import java.util.Map;

import com.fujitsu.futurity.web.x31.X31CID;
import com.fujitsu.futurity.web.x31.X31CWebConst;
import com.fujitsu.futurity.web.x31.X31SDataBeanAccess;
import com.fujitsu.futurity.web.x33.X33SException;

import eo.common.constant.JPCModelConstant;
import eo.common.constant.JPCOnlineMessageConstant;
import eo.web.webview.JCCWebBusinessLogic;
import eo.web.webview.CommonInfoCF.CommonInfoCFConst;
import eo.web.webview.common.JCCWebCommon;
import eo.web.webview.common.JCRScreenConst;
import eo.web.webview.common.JCRWebCommon;
import eo.web.webview.mapping.CRSV0272_CRSV0272OPDBMapper;

/**
 * OPMSログインビューロジック.<p>
 * <BR>
 * @author 富士通
 */
@SuppressWarnings("serial")
public class CRW10501SFLogic extends JCCWebBusinessLogic
{
	/**
	 * セッション格納キー
	 */
	public static final String SESSION_KEY = "CRW10501_SESSION_KEY";

	/**
	 * REPLACE_MAP
	 */
	private static final Map<String, String> REPLACE_MAP = new HashMap<String, String>();

	/**
	 * 置換表
	 */
	static {
		REPLACE_MAP.put("0", "A");
		REPLACE_MAP.put("1", "C");
		REPLACE_MAP.put("2", "E");
		REPLACE_MAP.put("3", "G");
		REPLACE_MAP.put("4", "I");
		REPLACE_MAP.put("5", "K");
		REPLACE_MAP.put("6", "M");
		REPLACE_MAP.put("7", "O");
		REPLACE_MAP.put("8", "Q");
		REPLACE_MAP.put("9", "S");
	}

	/**
	 * 1byteのデータから生成される文字数
	 */
	private static final int STRING_SIZE = 2;

	/**
	 * 親クラスX31BWebBusinessLogicのreceiveMessageWebを
	 * オーバーライドして自動生成されたメソッドです。
	 * @param arg0 (I) イベント情報
	 * @param arg1 (I) WebFWでは使用しません
	 * @param arg2 (I) WebFWでは使用しません
	 * @return 処理結果（true:正常終了、false:エラー）
	 * @throws X33SException X33SException
	 */
	@Override
	protected boolean receiveMessageWeb(X31CID arg0, Object arg1,
			EventObject arg2) throws X33SException
	{
		return false;
	}

	/**
	 * 初期表示処理<br>
	 * <br>
	 * OPMSログイン(初期表示)サービスを呼び出し、
	 * OPMSログイン画面の初期表示を行います。
	 * 
	 * @return boolean
	 * @throws Exception Exception
	 */
	@SuppressWarnings("unchecked")
	public boolean init() throws Exception
	{
		// サービスフォームBeanの内容の取得
		X31SDataBeanAccess bean = getServiceFormBean();

		// 共有フォームBeanの内容を取得
		X31SDataBeanAccess commoninfoBean = getCommonInfoBean();

		// -------------------------------------------------- //
		// (1)引継情報の取得
		// -------------------------------------------------- //
		// (a)sessionからOPMSログインmapを取得
		HashMap<String, Object> sessionMap = (HashMap<String, Object>)this.getSessionObject(SESSION_KEY);

		JCRWebCommon.getScreenInfo(this);

		// -------------------------------------------------- //
		// (2)サービスフォームBeanの設定
		// -------------------------------------------------- //
		// (a)サービスフォームBeanの項目をクリアする。
		clearBean();

		// (b)sessionにOPMSログインmapが存在する場合、ユーザーＩＤ、パスワードを設定
		if (sessionMap != null)
		{
			HashMap<String, Object> lstMap = (HashMap<String, Object>)sessionMap.get(true);

			if (lstMap != null)
			{
				if (lstMap.containsKey(CRW10501SFConst.USER_ID))
				{
					bean.sendMessageString(CRW10501SFConst.USER_ID, X31CWebConst.DATABEAN_SET_VALUE,
							(String)lstMap.get(CRW10501SFConst.USER_ID));
				}
				if (lstMap.containsKey(CRW10501SFConst.PASSWORD))
				{
					bean.sendMessageString(CRW10501SFConst.PASSWORD, X31CWebConst.DATABEAN_SET_VALUE,
							(String)lstMap.get(CRW10501SFConst.PASSWORD));
				}
			}
		}

		// -------------------------------------------------- //
		// (3)サービス呼出処理
		// -------------------------------------------------- //
		// ユースケースID格納用マップ
		HashMap<Object, String> paramMap = new HashMap<Object, String>();
		
		// ユースケースID格納
		paramMap.put(X31CWebConst.TELEGRAM_INFO_USECASE_ID, "CRSV0272");
		
		// マッピングクラス
		CRSV0272_CRSV0272OPDBMapper mapper = new CRSV0272_CRSV0272OPDBMapper();
		
		// マッピング用Map
		HashMap<String, Object> dataMap = new HashMap<String, Object>();

		// マッピングクラスを使用する為、配列化
		X31SDataBeanAccess[] paramBean = {bean};
		
		mapper.setGETOUTURL1RCC(paramBean, dataMap, JPCModelConstant.FUNC_CD_1);
		
		// サービス実行結果データ用Map
		HashMap<String, Object> outputMap = new HashMap<String, Object>();

		// サービス実行
		invokeService(paramMap, dataMap, outputMap);
		
		// -------------------------------------------------- //
		// (4)サービス処理結果の設定
		// -------------------------------------------------- //
		mapper.getGETOUTURL1RCC(paramBean, outputMap);

		// -------------------------------------------------- //
		// (5)引継情報の設定
		// -------------------------------------------------- //
		// なし。

		// -------------------------------------------------- //
		// (6)共有フォームBeanの設定
		// -------------------------------------------------- //
		// 初期表示メッセージ設定
		JCCWebCommon.setMessageInfo(this, JPCOnlineMessageConstant.EKB6070__I);

		// 遷移先画面IDを共有フォームBeanに設定
		commoninfoBean.sendMessageString(CommonInfoCFConst.NEXT_SCREEN_ID, X31CWebConst.DATABEAN_SET_VALUE,
				JCRScreenConst.SCREEN_ID_CRW10501);

		// 遷移先画面名を共有フォームBeanに設定
		commoninfoBean.sendMessageString(CommonInfoCFConst.NEXT_SCREEN_NAME, X31CWebConst.DATABEAN_SET_VALUE,
				JCRScreenConst.SCREEN_NAME_CRW10501);

		return true;

	}

	/**
	 * ログイン処理<br>
	 * <br>
	 * タイムスタンプの暗号化、パスワードをハッシュ値化し、
	 * OPMSシステムの画面起動を行います。
	 * 同時にセッションにユーザーID、パスワードを保持します。
	 * 
	 * @return boolean
	 * @throws Exception Exception
	 */
	public boolean login() throws Exception
	{
		// サービスフォームBeanの内容の取得
		X31SDataBeanAccess bean = getServiceFormBean();

		// 共有フォームBeanの内容を取得
		X31SDataBeanAccess commoninfoBean = getCommonInfoBean();

		// -------------------------------------------------- //
		// (1)引継情報の取得
		// -------------------------------------------------- //
		// なし。

		// -------------------------------------------------- //
		// (2)サービスフォームBeanの設定
		// -------------------------------------------------- //
		// 入力されたパスワード
		String orgPass = bean.sendMessageString(CRW10501SFConst.PASSWORD, X31CWebConst.DATABEAN_GET_VALUE);
		// パスワードのハッシュ値
		bean.sendMessageString(CRW10501SFConst.PASSWORD_HASH_VALUE, X31CWebConst.DATABEAN_SET_VALUE, getPasswordHashValue(orgPass));
		// システム日付を暗号化
		bean.sendMessageString(CRW10501SFConst.SYS_DATE_TIME, X31CWebConst.DATABEAN_SET_VALUE, encryptTimestamp(JCRWebCommon.getSysDateTime()));
		// ＯＰＭＳシステムＵＲＬを設定
		bean.sendMessageString(CRW10501SFConst.OPMS_URL, X31CWebConst.DATABEAN_SET_VALUE, getOpmsUrl());
		// ＯＰＭＳ起動フラグを設定
		bean.sendMessageString(CRW10501SFConst.OPMS_OPEN_FLG, X31CWebConst.DATABEAN_SET_VALUE, "1");

		// -------------------------------------------------- //
		// (3)サービス呼出処理
		// -------------------------------------------------- //
		// なし。

		// -------------------------------------------------- //
		// (4)サービス処理結果の設定
		// -------------------------------------------------- //
		// なし。

		// -------------------------------------------------- //
		// (5)引継情報の設定
		// -------------------------------------------------- //
		// 引き継ぎの情報を格納するMAPを生成する。 
		HashMap<String, Object> hktgMap = new HashMap<String, Object>();

		// ユーザーＩＤ
		hktgMap.put(CRW10501SFConst.USER_ID,
				bean.sendMessageString(CRW10501SFConst.USER_ID, X31CWebConst.DATABEAN_GET_VALUE));
		// パスワード
		hktgMap.put(CRW10501SFConst.PASSWORD,
				bean.sendMessageString(CRW10501SFConst.PASSWORD, X31CWebConst.DATABEAN_GET_VALUE));

		// sessionにOPMSログインmapを設定
		this.setSessionObject(SESSION_KEY, hktgMap);

		// -------------------------------------------------- //
		// (6)共有フォームBeanの設定
		// -------------------------------------------------- //
		// 遷移先画面IDを共有フォームBeanに設定
		commoninfoBean.sendMessageString(CommonInfoCFConst.NEXT_SCREEN_ID, X31CWebConst.DATABEAN_SET_VALUE,
				JCRScreenConst.SCREEN_ID_CRW10501);

		// 遷移先画面名を共有フォームBeanに設定
		commoninfoBean.sendMessageString(CommonInfoCFConst.NEXT_SCREEN_NAME, X31CWebConst.DATABEAN_SET_VALUE,
				JCRScreenConst.SCREEN_NAME_CRW10501);

		return true;

	}

	/**
	 * Timestamp暗号化処理<br>
	 * <br>
	 * Timestampの文字列(14桁)を暗号化した値を返します。
	 * 
	 * @param timestamp
	 * @return String Timestampの文字列(14桁)を暗号化した値
	 */
	private String encryptTimestamp(String timestamp)
	{
		// 年月日時分秒の下一桁
		String strLast = timestamp.substring(13, 14);
		int intLast = Integer.parseInt(strLast);

		// 置換表に従い、置換された文字列
		StringBuilder repStr = new StringBuilder();

		// 秒の下一桁自身以外に対する処理
		for (int i = 0; i < 13; i++)
		{
			// 年月日時分秒の各桁に秒の下一桁を足し、その足した値の下一桁を設定（秒の下一桁自身には足さない）
			char ch = timestamp.charAt(i);
			int num = (Character.digit(ch, 10) + intLast) % 10;

			// 置換表に従ってアルファベットに置換
			repStr.append(REPLACE_MAP.get(String.valueOf(num)));
		}

		// 下一桁を置換表に従ってアルファベットに置換
		repStr.append(REPLACE_MAP.get(strLast));

		// 固定のパターンに従って文字列を並び替え
		StringBuilder encStr = new StringBuilder();

		// 1文字目
		encStr.append(repStr.substring(0, 1));
		// 2文字目
		encStr.append(repStr.substring(12, 13));
		// 3文字目
		encStr.append(repStr.substring(2, 3));
		// 4文字目
		encStr.append(repStr.substring(10, 11));
		// 5文字目
		encStr.append(repStr.substring(4, 5));
		// 6文字目
		encStr.append(repStr.substring(8, 9));
		// 7文字目
		encStr.append(repStr.substring(6, 7));
		// 8文字目
		encStr.append(repStr.substring(13, 14));
		// 9文字目
		encStr.append(repStr.substring(1, 2));
		// 10文字目
		encStr.append(repStr.substring(11, 12));
		// 11文字目
		encStr.append(repStr.substring(3, 4));
		// 12文字目
		encStr.append(repStr.substring(9, 10));
		// 13文字目
		encStr.append(repStr.substring(5, 6));
		// 14文字目
		encStr.append(repStr.substring(7, 8));

		return encStr.toString();
	}

	/**
	 * ハッシュ値取得処理<br>
	 * <br>
	 * パスワードのハッシュ値を返します。
	 * ハッシュ値算出アルゴリズムはSHA-1で2回変換する。
	 * 
	 * @param orgPassword
	 * @return String ハッシュ値
	 * @throws NoSuchAlgorithmException 
	 */
	private String getPasswordHashValue(String orgPassword) throws NoSuchAlgorithmException
	{
		String hashValue = "";
		try
		{
			MessageDigest md = MessageDigest.getInstance("SHA-1");
			byte[] digest1 = md.digest(orgPassword.getBytes());
			hashValue = byteArrayToHexString(digest1);
			byte[] digest2 = md.digest(hashValue.getBytes());
			hashValue = byteArrayToHexString(digest2);
		}
		catch (NoSuchAlgorithmException e)
		{
//			e.printStackTrace();
			throw e;
		}
		return hashValue;
	}

	/**
	 * バイト配列を16進数の文字列に変換
	 * @param arg      バイト配列
	 * @return String  16進数に変換した文字列
	 */
	private static String byteArrayToHexString(byte[] arg)
	{
		StringBuilder byteArray = new StringBuilder();
		for (int i = 0; i < arg.length; i++)
		{
			// 暗号化されたバイト配列の要素を16進表現の文字列に変換
			String strByteCode = String.format("%02x", arg[i]);
			byteArray.append(strByteCode);
		}
		return byteArray.toString();
	}

    /**
	 * サービスフォームBeanのクリア処理<br>
	 * <br>
	 * サービスフォームBeanの引継ぎ項目以外の値をクリアします。
	 * 引継ぎ項目：サービス契約番号
	 * 
	 */
	private void clearBean()
	{
		// サービスフォームBeanの内容の取得
		X31SDataBeanAccess bean = getServiceFormBean();

		// サービスフォームBeanの項目をクリアする。
		bean.sendMessage(CRW10501SFConst.USER_ID, X31CWebConst.DATABEAN_CLEAR);
		bean.sendMessage(CRW10501SFConst.PASSWORD, X31CWebConst.DATABEAN_CLEAR);
		bean.sendMessage(CRW10501SFConst.PASSWORD_HASH_VALUE, X31CWebConst.DATABEAN_CLEAR);
		bean.sendMessage(CRW10501SFConst.SYS_DATE_TIME, X31CWebConst.DATABEAN_CLEAR);
		bean.sendMessage(CRW10501SFConst.OPMS_URL, X31CWebConst.DATABEAN_CLEAR);
		bean.sendMessage(CRW10501SFConst.OPMS_OPEN_FLG, X31CWebConst.DATABEAN_CLEAR);
	}

    /**
	 * OPMSシステムURL取得処理<br>
	 * <br>
	 * URLに含まれている特定の文字列をサービスフォームBeanの内容で置換します。
	 * @return String  OPMSシステムURL
	 */
	private String getOpmsUrl()
	{
		// サービスフォームBeanの内容の取得
		X31SDataBeanAccess bean = getServiceFormBean();

		// サービス契約番号
		String svcKeiNo = bean.sendMessageString(CRW10501SFConst.SVC_KEI_NO, X31CWebConst.DATABEAN_GET_VALUE);
		// ユーザーＩＤ
		String userId = bean.sendMessageString(CRW10501SFConst.USER_ID, X31CWebConst.DATABEAN_GET_VALUE);
		// パスワード（ハッシュ値）
		String passWord = bean.sendMessageString(CRW10501SFConst.PASSWORD_HASH_VALUE, X31CWebConst.DATABEAN_GET_VALUE);
		// システム日時（暗号化済）
		String sysDateTime = bean.sendMessageString(CRW10501SFConst.SYS_DATE_TIME, X31CWebConst.DATABEAN_GET_VALUE);
		// ＯＰＭＳシステムＵＲＬ
		String url = bean.sendMessageString(CRW10501SFConst.OPMS_URL, X31CWebConst.DATABEAN_GET_VALUE);

		url = url.replaceAll("%NET_SVC_KEI_NO%", svcKeiNo);
		url = url.replaceAll("%OPERATORCODE%", userId);
		url = url.replaceAll("%PS%", passWord);
		url = url.replaceAll("%V%", sysDateTime);

		return url;
	}

}
