/*********************************************************************
 * All Rights reserved,Copyright (c) K-Opticom
 **********************************************************************
 *＜プログラム内容＞
 *   システム名      ：eo顧客基幹システム
 *   モジュール名    ：JFUTvCmpMongonInfoArea
 *   ソースファイル名：JFUTvCmpMongonInfoArea.java
 *   作成者          ：富士通
 *   日付            ：2012年07月10日
 *＜機能概要＞
 *   フロント画面キャンペーン文言一覧領域出力部品です。
 *＜修正履歴＞
 *   バージョン  修正日       修正者      修正内容
 *   v5.00.00    2013/05/18   FJ）瀧澤    新規作成
 *   v15.00.00   2015/10/14   FJ）西川   【OM-2015-0002416】XML情報の欠落事象対応
 *
 **********************************************************************/
package eo.web.webview.common;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspException;

import com.fujitsu.futurity.web.x33.DispatchContext;
import com.fujitsu.futurity.web.x33.DispatchContextFactory;
import com.fujitsu.futurity.web.x33.HttpDispatchContext;
import com.fujitsu.futurity.web.x33.X33SDataBeanAccessWrapper;
import com.fujitsu.futurity.web.x33.X33SErrorLog;
import com.fujitsu.futurity.web.x33.X33VCustomTagBase;
import com.fujitsu.futurity.web.x33.beans.X33VDataTypeList;
import com.fujitsu.futurity.web.x33.beans.X33VViewBaseBean;
import com.fujitsu.futurity.web.x33.beans.X33VViewJSPBean;

import eo.common.constant.JFUStrConst;

/**
 * フロント画面TVキャンペーン文言一覧領域出力部品です。
 * <br>
 * @author 富士通
 */
@SuppressWarnings("serial")
public class JFUTvCmpMongonInfoArea extends X33VCustomTagBase
{
	/** 拡張タグテンプレートファイルのテンプレートID */
	private static final String TAG_TEMPLATE = "TagTemplate013";
	/** 項目ID：料金コースコード */
	private static final String PCRS_CD = "pcrs_cd";
	/** BSパススルー出力判定設定値（項目パスのキー） */
	private static final String BSPASS = "bspass";
	/** BSパススルー出力判定設定値（項目パスのキー） */
	private static final String CNG_BSPASS = "cng_bspass";
	/** BSパススルー出力判定設定値（項目パスのキー） */
	private static final String MSKM_BSPASS = "mskm_bspass";

	/** CHANGE_IMG_PATH */
	private static final String CHANGE_IMG_PATH = "CHANGE_IMG_PATH";
	/** 置換用 サービスフォームＩＤ */
	private static final String REPLACE_SF_ID = "%serviceFormID%";
	/** 空文字 */
	private static final String BLANK = "";
	/** ＢＳパススルーのキャンペーン表示用設定値 */
	private static final String DISP_FLG = "1";
	/** ＢＳパススルーの申込フラグ */
	private static final String MSKM_FLG = "1";

	/** タグスタイル定数 ul */
	private static final String TAG_TYPE_UL = "ul";
	/** タグスタイル定数 p */
	private static final String TAG_TYPE_P = "p";
	/** タグスタイル定数 header */
	private static final String TAG_TYPE_HEADER = "header";
	/** デフォルト表示場所コード */
	private static final String DEFAULT_DISP_PlACE_CD = "00";

	/** 定義取得パス*/
	private static final String QUERY_PATH_LINK = "DISPSETTING/SETTING[@screenId='%1%']/OUTLINK[@groupid='BSPT_LINK']";
	/** 属性名 */
	private static final String QUERY_ATTR_NAME = "id";
	/** BSパススルー用のリンクID */
	private static final String BSPT_LINK_ID = "bspt_link";
	/** 置き換え文字列1 */
	private static final String RE_1 = "%1%";
	/** BSパススルー用の置き換え文字 */
	private static final String REPlACE_BSPT_LINK = "BSPT_LINK";

	/** 出力文言定数 共通1 */
	private static final String TAG_MONGON_CMN_1 = "<div class=\"mt_em\"></div>";
	/** 出力文言定数 共通2 */
	private static final String TAG_MONGON_CMN_2 = "<p>お客様向けのお得なeo光テレビキャンペーンのご案内</p>";

	/** 出力文言定数 ulタグタイプ1 */
	private static final String TAG_MONGON_UL_1 = "<ul class=\"ulDisc mt_em\" >";
	/** 出力文言定数 ulタグタイプ2 */
	private static final String TAG_MONGON_UL_2 = "<li>";
	/** 出力文言定数 ulタグタイプ3 */
	private static final String TAG_MONGON_UL_3 = "</li>";
	/** 出力文言定数 ulタグタイプ4 */
	private static final String TAG_MONGON_UL_4 = "</ul>";
	/** 出力文言定数 pタグタイプ1 */
	private static final String TAG_MONGON_P_1 = "<p class=\"caution\">";
	/** 出力文言定数 pタグタイプ2 */
	private static final String TAG_MONGON_P_2 = "</p>";

	/** 取得用メソッド名：キャンペーン文言リスト */
	private static final String MTD_NM_GET_CMP_MONGON_LIST = "getCmp_mongon_list_list";
	/** 取得用メソッド名：キャンペーン文言 */
	private static final String MTD_NM_GET_CMP_MONGON = "getCmp_mongon_value";
	/** 取得用メソッド名：キャンペーン文言種別コード */
	private static final String MTD_NM_GET_CMP_MONGON_SBT_CD = "getCmp_mongon_sbt_cd_value";
	/** 取得用メソッド名：表示場所コード */
	private static final String MTD_NM_GET_DISP_PLACE_CD = "getDisp_place_cd_value";
	/** 取得用メソッド名：料金コースコード */
	private static final String MTD_NM_GET_PCRS_CD = "getPcrs_cd_value";

	/** エラーメッセージ：キャンペーン文言リスト領域の取得失敗時エラー */
	private static final String ERR_MSG_EXIST_CMP_MG_AREA = "キャンペーン文言リストの存在チェックでエラー。";

	/** ユーザ情報に表示させるパターン属性 */
	private String screen = BLANK;
	/** 表示するキャンペーン文言種別コードの属性 */
	private String cmpMongonSbt = BLANK;
	/** 表示場所を指定するコードの属性 */
	private String dispPlaceCd = BLANK;
	/** タグタイプ */
	private String tagType = BLANK;

	/**
	 * カスタムタグ開始処理を行います。
	 * <br>
	 * @throws	JspException JSPで発生する例外
	 * @return 処理結果
	 * @see javax.servlet.jsp.tagext.TagSupport#doStartTag()
	 */
	@Override
	public int doStartTag() throws JspException
	{
		/*
		 * ==============================================================
		 * キャンペーン文言エリア表示処理(サービスフォームBeanからの情報取得処理) START
		 * ==============================================================
		 */
		X33VViewJSPBean jspBean = getJspBean();

		// サービスフォームビーンのIDのリストが取得できない場合はタグを作成しない。
		if (null == jspBean.getServiceFormIdList() || 0 == jspBean.getServiceFormIdList().size())
		{
			return SKIP_BODY;
		}

		// サービスフォームビーンのIDを取得する。
		String serviceFormId = null;
		for (int i = 0; i < jspBean.getServiceFormIdList().size(); i++)
		{

			String sessionServiceFormId = (String)jspBean.getServiceFormIdList().get(i);
			if (sessionServiceFormId.startsWith(screen))
			{
				serviceFormId = sessionServiceFormId;
				break;
			}
		}
		// サービスフォームビーンのIDが取得できない場合はタグを作成しない。
		if (null == serviceFormId)
		{
			return SKIP_BODY;
		}

		// キャンペーン文言リストの存在チェック処理を実施する。
		// キャンペーン文言リストが存在する場合、出力対象のキャンペーン文言リストを取得する。
		// キャンペーン文言リストが存在しない場合、タグを作成しない。
		Set<String> cmpMongonSet = new LinkedHashSet<String>();
		if (!isExistCmpMongonInfoArea(jspBean, serviceFormId, cmpMongonSet))
		{
			return SKIP_BODY;
		}

		/*
		 * ==============================================================
		 * キャンペーン文言エリア表示処理(サービスフォームBeanからの情報取得処理) END
		 * ==============================================================
		 */

		/*
		 * ==============================================================
		 * キャンペーン文言エリア表示処理(HTML出力) START
		 *
		 * ==============================================================
		 */
		if (TAG_TYPE_UL.equals(tagType))
		{
			// タグタイプの指定が"ul"の場合は、<ul>タグで囲まれた情報を出力する
			outputHtml(TAG_MONGON_CMN_1 + JFUStrConst.RETURN_CODE);
			outputHtml(TAG_MONGON_CMN_2 + JFUStrConst.RETURN_CODE);
			outputHtml(TAG_MONGON_UL_1 + JFUStrConst.RETURN_CODE);

			for (String cmpMongon : cmpMongonSet)
			{
				outputHtml(TAG_MONGON_UL_2 + JFUStrConst.RETURN_CODE);
				outputHtml(cmpMongon + JFUStrConst.RETURN_CODE);
				outputHtml(TAG_MONGON_UL_3 + JFUStrConst.RETURN_CODE);
			}
			outputHtml(TAG_MONGON_UL_4 + JFUStrConst.RETURN_CODE);
		}
		else if (TAG_TYPE_P.equals(tagType))
		{
			// <p>タグで囲まれた情報を出力する
			for (String cmpMongon : cmpMongonSet)
			{
				outputHtml(TAG_MONGON_P_1 + JFUStrConst.RETURN_CODE);
				outputHtml(cmpMongon + JFUStrConst.RETURN_CODE);
				outputHtml(TAG_MONGON_P_2 + JFUStrConst.RETURN_CODE);
			}
		}
		else
		{
			// タグタイプの指定が無い場合は、そのまま出力する
			// HEADER指定の場合、共通の文言を出力する
			if (TAG_TYPE_HEADER.equals(tagType))
			{
				outputHtml(TAG_MONGON_CMN_1 + JFUStrConst.RETURN_CODE);
				outputHtml(TAG_MONGON_CMN_2 + JFUStrConst.RETURN_CODE);
			}

			for (String cmpMongon : cmpMongonSet)
			{
				outputHtml(cmpMongon + JFUStrConst.RETURN_CODE);
			}
		}
		/*
		 * ==============================================================
		 * キャンペーン文言エリア表示処理(HTML出力) END
		 * ==============================================================
		 */

		return SKIP_BODY;
	}

	/**
	 * スクリーンを設定します。
	 * <br>
	 * @param paramScreen スクリーン
	 */
	public void setScreen(String paramScreen)
	{
		this.screen = paramScreen;
	}

	/**
	 * キャンペーン文言種別コードを設定します。
	 * @param paramCmpMongonSbt キャンペーン文言種別コード
	 */
	public void setCmpMongonSbt(String paramCmpMongonSbt)
	{
		this.cmpMongonSbt = paramCmpMongonSbt;
	}

	/**
	 * 表示場所のコードを設定します。
	 * @param paramDispPlaceCd 表示場所コード
	 */
	public void setDispPlaceCd(String paramDispPlaceCd)
	{
		if (JFUWebCommon.isNull(paramDispPlaceCd))
		{
			this.dispPlaceCd = DEFAULT_DISP_PlACE_CD;
		}
		else
		{
			this.dispPlaceCd = paramDispPlaceCd;
		}
	}

	/**
	 * キャンペーン文言一覧の表示スタイルを設定します。
	 * @param paramTagType キャンペーン文言一覧を表示するスタイル
	 */
	public void setTagType(String paramTagType)
	{
		this.tagType = paramTagType;
	}

	/**
	 * <DL>
	 * <DT>JSPBeanを取得します。
	 * </DL>
	 * @return
	 * @throws JspException
	 */
	private X33VViewJSPBean getJspBean() throws JspException
	{

		// JSPビーンを取得する（取得できなかったらエラーを投げる）
		X33VViewJSPBean jspBean = null;

		DispatchContext context = DispatchContextFactory.getInstance().getHttpDispatchContext();
		HttpServletRequest request = ((HttpDispatchContext)context).getServletRequest();

		Object areaIdObj = request.getAttribute("nextPageAreaId");

		if (areaIdObj != null && areaIdObj instanceof String)
		{
			jspBean = (X33VViewJSPBean)context.getResponseBean((String)areaIdObj);
		}

		return jspBean;
	}

	/**
	 * <DL>
	 * <DT>テンプレート定義に記述した画面定義に誤りがある場合、ログを出力してエラー画面に
	 * なります。ログには引数で指定したエラーメッセージが出力されます。
	 * </DL>
	 * <p>
	 *
	 * @param  errormsg エラーメッセージ
	 * @throws JspException
	 */
	private void throwJspException(String errormsg, Throwable th) throws JspException
	{

		// テンプレートに記載した画面定義に誤りがある場合、警告ログを出力しエラーを投げる
		JspException se = new JspException(errormsg);
		if (null != th)
		{
			se.initCause(th);
		}

		X33SErrorLog.outputSystemError(this.getClass(), se, DispatchContextFactory.getInstance().getHttpDispatchContext());
		throw se;
	}

	/**
	 * キャンペーン文言リストの存在チェック処理
	 *
	 * <br>
	 * @param jspBean
	 * @param serviceFormId サービスフォームID
	 * @param cmpMongonSet 出力対象のキャンペーン文言一覧リスト
	 * @return true:存在する場合、false:存在しない場合
	 * @throws JspException
	 */
	private boolean isExistCmpMongonInfoArea(X33VViewJSPBean jspBean, String serviceFormId, Set<String> cmpMongonSet) throws JspException
	{
		X33VViewBaseBean targetBean = null;
		// サービスフォームビーンを検索
		ArrayList<?> sfBeanArray = jspBean.listServiceFormBeanListForX31();
		for (int i = 0; i < sfBeanArray.size(); i++)
		{
			// サービスフォームビーン取得
			X33VViewBaseBean tmpBean = (X33VViewBaseBean)sfBeanArray.get(i);
			if (tmpBean.getServiceFormId().equals(serviceFormId))
			{
				targetBean = tmpBean;
			}
		}

		if (null == targetBean)
		{
			return false;
		}

		// 料金コースの取得
		String cmBeanPcrsCd = getDataString(PCRS_CD, 0);

		Class<?> cls = targetBean.getClass();
		Method method = null;
		X33VDataTypeList tmpListObj = null;
		try
		{
			method = cls.getDeclaredMethod(MTD_NM_GET_CMP_MONGON_LIST);
			Object[] obj = null;
			tmpListObj = (X33VDataTypeList)method.invoke(targetBean, obj);
			// キャンペーン文言リストが取得できなかった場合は、存在しない場合と判定する
			if (tmpListObj == null)
			{
				return false;
			}
			// URL置換用データの取得
			String linkPath = QUERY_PATH_LINK.replace(RE_1, serviceFormId.substring(0, 8));
			Map<String, String> linkInfo = JFUWebCommon.getLinkItemsAsMap(linkPath, QUERY_ATTR_NAME);

			/* サービスフォームビーンの値を取得 */
			// BSパススルー情報表示フラグ
			String beanBspass = getBeanItem(jspBean, serviceFormId, BSPASS);
			// BSパススルー変更可能フラグ(FUW09501 メニューから遷移してきた場合のみ設定)
			String beanCngBspass = getBeanItem(jspBean, serviceFormId, CNG_BSPASS);
			// BSパススルー申込フラグ
			String beanMskmBspass = getBeanItem(jspBean, serviceFormId, MSKM_BSPASS);

			for (int i = 0; i < tmpListObj.size(); i++)
			{
				// キャンペーン文言を保持しているBeanクラスの情報を取得する
				Class<?> clazz = tmpListObj.get(i).getClass();
				// キャンペーン文言取得実行メソッドの取得
				Method getCmpMongonMethod = clazz.getMethod(MTD_NM_GET_CMP_MONGON);
				String cmpMongon = (String)getCmpMongonMethod.invoke(tmpListObj.get(i));
				// キャンペーン文言種別コード取得実行メソッドの取得
				Method getCmpMongonSbtMethod = clazz.getMethod(MTD_NM_GET_CMP_MONGON_SBT_CD);
				String cmpMongonSbtCd = (String)getCmpMongonSbtMethod.invoke(tmpListObj.get(i));
				// キャンペーン文言表示箇所コード取得実行メソッドの取得
				Method getDispPlaceMethod = clazz.getMethod(MTD_NM_GET_DISP_PLACE_CD);
				String dispPlaceCd = (String)getDispPlaceMethod.invoke(tmpListObj.get(i));
				// キャンペーン文言料金コース取得実行メソッドの取得
				Method getPcrsCdMethod = clazz.getMethod(MTD_NM_GET_PCRS_CD);
				String pcrsCd = (String)getPcrsCdMethod.invoke(tmpListObj.get(i));

				// 指定した種別コード、表示箇所、料金コースの場合、リストに追加する
				if (this.cmpMongonSbt.equals(cmpMongonSbtCd) && this.dispPlaceCd.equals(dispPlaceCd) && cmBeanPcrsCd.equals(pcrsCd))
				{
					// ＢＳパススルーのキャンペーンの場合、表示／非表示をBSパススルー出力判定設定値により振り分ける
					if (DISP_FLG.equals(beanBspass) || DISP_FLG.equals(beanCngBspass))
					{
						// 確認画面、完了画面は申込時のみ表示となる為申込フラグを確認する
						if (JFUStrConst.CD01291_02.equals(this.cmpMongonSbt) || JFUStrConst.CD01291_03.equals(this.cmpMongonSbt))
						{
							if (!MSKM_FLG.equals(beanMskmBspass))
							{
								continue;
							}
						}

						// 置換
						// プロパティファイルからパスを取得
						String changeImgPath = JFUWebCommon.getApplicationConst(CHANGE_IMG_PATH);
						cmpMongon = cmpMongon.replace(JFUStrConst.PERCENT + CHANGE_IMG_PATH + JFUStrConst.PERCENT, changeImgPath);
						String newWindowPath = linkInfo.get(BSPT_LINK_ID);
						cmpMongon = cmpMongon.replace(JFUStrConst.PERCENT + REPlACE_BSPT_LINK + JFUStrConst.PERCENT, newWindowPath);
						// 出力対象のキャンペーン文言セットを追加
						cmpMongonSet.add(cmpMongon);
					}
				}
			}
		}
		catch (NoSuchMethodException e)
		{
			throwJspException(ERR_MSG_EXIST_CMP_MG_AREA, e);
		}
		catch (IllegalAccessException e)
		{
			throwJspException(ERR_MSG_EXIST_CMP_MG_AREA, e);
		}
		catch (InvocationTargetException e)
		{
			throwJspException(ERR_MSG_EXIST_CMP_MG_AREA, e);
		}
		catch (Exception e)
		{
			throwJspException(ERR_MSG_EXIST_CMP_MG_AREA, e);
		}
		// 出力対象のキャンペーン文言リストの要素が0の場合、存在しない場合と判定する
		return cmpMongonSet.size() > 0;
	}

	/**
	 * サービスフォームビーンの値を取得
	 *
	 * <br>
	 * @param jspBean
	 * @param serviceFormId サービスフォームID
	 * @param itemName 項目の名前
	 * @return サービスビーンの該当する項目の値
	 */
	private String getBeanItem(X33VViewJSPBean jspBean, String serviceFormId, String itemName)
	{
		String beanItem = JFUStrConst.EMPTY;
		String replaceKey = JFUStrConst.EMPTY;

		// フロント用画面表示定義ファイルからサービスフォームビーンの項目のパスを取得
		try
		{
			replaceKey = JFUWebCommon.getDispText(serviceFormId.substring(0, 8), itemName);
			if(JFUWebCommon.isNull(replaceKey)){
				return beanItem;
			}
		}
		catch (Exception e)
		{
			// エラー時は、値はから文字で抜ける。
			return beanItem;
		}
		// それぞれの画面にあわせてサービスフォームＩＤを置換
		replaceKey = replaceKey.replace(REPLACE_SF_ID, serviceFormId);
		// サービスフォームビーンから値を取得
		beanItem =
				(String)X33SDataBeanAccessWrapper.execJSPBeanAccess(null, jspBean, replaceKey, X33SDataBeanAccessWrapper.REQ_GET_VALUE,
						X33SDataBeanAccessWrapper.SUBKEY_VALUE, null);

		return beanItem;

	}

	/**
	 * 共有フォームBeanより項目を取得します。(階層構造型)
	 * <br>
	 * @param arg0
	 * @param idx
	 * @return 項目
	 */
	private String getDataString(String arg0, int idx)
	{
		String str = null;
		try
		{
			str = getSFBeanData_String(TAG_TEMPLATE, arg0, idx);
			if (str == null || "null".equals(str))
			{
				str = "";
			}
		}
		catch (Exception e)
		{
			str = "";
		}
		return str;
	}

}
