/*********************************************************************
*  All Rights reserved,Copyright (c) K-Opticom
**********************************************************************
*＜プログラム内容＞
*	システム名			：eo顧客基幹システム
*	モジュール名		：JBSbatACWrbSvcLmtKykNoStk
*	ソースファイル名	：JBSbatACWrbSvcLmtKykNoStk.java
*	作成者				：富士通　
*	作成日				：2012年02月14日
*＜機能概要＞
*　割引サービスコード・上限契約数取得部品です。
*＜修正履歴＞
*	バージョン	修正日		修正者		修正内容
*	v1.00.00	2012/02/14   富士通		新規作成
*	v3.00		2012/08/01   FJ)本多	【ST2-2012-0001323対応】休止判定処理の追加、及び、上限契約数の取得スキーマ変更
*********************************************************************/
package eo.business.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;

import eo.business.common.JACbatDebugLogUtil;
import eo.business.common.JACbatParamUtil;
import eo.business.common.JACbatSchdlUtil;
import eo.business.common.JBSbatBusinessService;
import eo.business.util.file.JBSbatACIFI015;
import eo.business.util.file.JBSbatACIFM128;
import eo.common.constant.JACStrConst;
import eo.common.util.JPCUtilCommon;
import eo.framework.item.JBSbatCommonItem;
import eo.framework.item.JBSbatOutputItem;
import eo.framework.item.JBSbatServiceInterfaceMap;

/**
* (クラスの機能概要) <p>
*<BR>
* @author 富士通
*/
public class JBSbatACWrbSvcLmtKykNoStk extends JBSbatBusinessService
{
	/**▼▼▼▼▼▼ツールから生成した宣言です 開始▼▼▼▼▼▼*/
	/**▲▲▲▲▲▲ツールから生成した宣言です 終了▲▲▲▲▲▲*/

	/** 利用月翌月月初日 */
	private String nextCycTukiSt		= null;
	
	/** 割引適用上限判定マップ（キー：料金グループコード＋料金コースコード＋料金サービスコード、値：｛割引サービスコード, 上限契約数｝） */
	private HashMap<String, ArrayList<String[]>> jdgMap = null;
	
	/**
	 * 初期処理
	 * @param JBSbatCommonItem commonItem バッチ共通パラメータ電文
	 * @throws Exception                  業務サービス内で発生した例外全般。
	 */
	public void initial(JBSbatCommonItem commonItem) throws Exception
	{
	/**▼▼▼▼▼▼業務サービスの初期処理を記述してください。▼▼▼▼▼▼*/
		/**▼▼▼▼▼▼ツールから生成した初期化のソースです 開始▼▼▼▼▼▼*/
		// 共通パラメータを設定します
		super.setCommonInfo(commonItem);
		/**▲▲▲▲▲▲ツールから生成した初期化のソースです 終了▲▲▲▲▲▲*/
		
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][initial]");
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][initial][opeDate=" + super.opeDate + "]");
		assert 	JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][initial][freeItem=" + super.freeItem + "]");
		
		// 翌月群月初日の取得
		this.getNextCycTukiSt();

		// 割引適用上限判定マップ作成
		this.getWrbSvcTanka();
		
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][initial]");
	/**▲▲▲▲▲▲業務サービスの初期処理を記述してください。▲▲▲▲▲▲*/
	}

	/**
	 * 主処理
	 * @param  inMap            入力電文
	 * @return JBSbatOutputItem 出力情報
	 * @throws Exception        業務サービス内で発生した例外全般。
	 */
	public JBSbatOutputItem execute(JBSbatServiceInterfaceMap inMap) throws Exception
	{
	/**▼▼▼▼▼▼業務サービスの主処理を記述してください。▼▼▼▼▼▼*/
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][execute]");
		assert inMap != null ? JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][execute][inMap=" + inMap.getMap().toString() + "]") : true;
		
		// 出力情報
		JBSbatOutputItem outputItem = new JBSbatOutputItem();
		
		// 割引適用上限判定判定マップ．キー取得
		String mapKey = this.makeMapKey(inMap);
		
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][execute][入力．キー=" + mapKey + "]");
		
		// 割引適用上限判定マップに入力．キーが含まれる場合
		if (this.jdgMap.containsKey(mapKey))
		{
			// 割引適用上限判定リスト
			ArrayList<String[]> valList = this.jdgMap.get(mapKey);
			
			// 休止判定
			// 休止と判定された場合、出力対象外とする。
			if (this.isPauseJudge(inMap))
			{
				// 何もしない。
			}
			else
			{
				// {割引サービスコード、上限契約数}の分、増幅してファイル出力する。
				for (int i = 0; i < valList.size(); i++)
				{
					// 出力処理
					outputItem.addOutMapList(makeOutInfo(inMap, valList.get(i)));
				}
			}
		}
		assert JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][execute]");
		
		return outputItem;
	/**▲▲▲▲▲▲業務サービスの主処理を記述してください。▲▲▲▲▲▲*/
	}

	/**
	 * 業務サービス終了処理
	 * @throws Exception 業務サービス内で発生した例外全般。
	 */
	public void terminal() throws Exception
	{
	/**▼▼▼▼▼▼業務サービスの終了処理を記述してください。▼▼▼▼▼▼*/
		/**▼▼▼▼▼▼ツールから生成した終了処理のソースです 開始▼▼▼▼▼▼*/
		/**▲▲▲▲▲▲ツールから生成した終了処理のソースです 終了▲▲▲▲▲▲*/
		
		assert 	JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][terminal]");
		assert 	JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][terminal]");
	/**▲▲▲▲▲▲業務サービスの終了処理を記述してください。▲▲▲▲▲▲*/
	}

	/**▼▼▼▼▼▼ツールから生成したメソッドです 開始▼▼▼▼▼▼*/
	/**▲▲▲▲▲▲ツールから生成したメソッドです 終了▲▲▲▲▲▲*/

	/**
	 * 翌月群月初日の取得
	 * @throws Exception 業務サービス内で発生した例外全般。
	 */
	private void getNextCycTukiSt() throws Exception
	{
		assert 	JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][getNextCycTukiSt]");
		
		// 請求年月
		String skyYmd = null;
		
		// 料金スケジュール定義部品の初期化
		JACbatSchdlUtil schdlUtil = new JACbatSchdlUtil(commonItem);
		
		// 請求年月取得処理 イベントコード:"03"(料金計算日)
		skyYmd = schdlUtil.getBillDate(super.opeDate, JACStrConst.EVENT_CD_RYOKIN_KEISAN_YMD);
		
		// イベント日付取得処理 イベントコード:"01"(利用開始日) "02"(利用終了日)
		String[] eveDay = schdlUtil.getUseStrEnd(skyYmd
												, JACStrConst.EVENT_CD_USE_STAYMD
												, JACStrConst.EVENT_CD_USE_ENDYMD);
		
		// 利用終了日＋1日して翌月月初日をもとめる
		this.nextCycTukiSt = JPCUtilCommon.addDay(eveDay[1], 1);

		assert 	JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][getNextCycTukiSt][翌月群月初日 nextCycTukiSt：" + this.nextCycTukiSt + "]");
		
		// 料金スケジュール定義クローズ
		schdlUtil.close();
		
		assert 	JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][getNextCycTukiSt]");
	}
	
	/**
	 * 割引適用上限判定マップ作成
	 * @throws Exception        業務サービス内で発生した例外全般。
	 */
	private void getWrbSvcTanka() throws Exception
	{
		assert 	JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][getWrbSvcTanka]");
		
		
		JACbatParamUtil paramUtil = new JACbatParamUtil(commonItem);
		
		assert 	JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][getWrbSvcTanka][業務パラメータ管理．検索条件：" + JACStrConst.WKPRA_KK_UPPL_KS + ", " + super.opeDate + "]");
		
		HashMap<String, String> dbMap = null;
		
		try
		{
			// 業務パラメータ取得
			dbMap = paramUtil.getGyoumuParameterMap2(JACStrConst.WKPRA_KK_UPPL_KS, super.opeDate);
		}
		finally
		{
			paramUtil.close();
		}
		
		
		// 割引適用上限判定マップ　生成
		this.jdgMap = new HashMap<String, ArrayList<String[]>>();
		
		// キーセット（業務パラメータID）
		Set<String> keySet = dbMap.keySet();
		// 反復子
		Iterator<String> iterator = keySet.iterator();
		
		while(iterator.hasNext())
		{
			String mapKey = iterator.next();
			
			// 業務パラメータ管理．設定値を":"で文字分割
			String[] workParamValue = dbMap.get(mapKey).split(JACStrConst.COLON);
			
			// 料金グループコード＋料金コースコード
			String workParmId = mapKey.substring(11);
			
			// (1)割引サービスコード
			// (2)上限契約数
			// (3)料金プランコード
			// (1)、(2)、(3)*nの繰り返し
			for(String trgStr : workParamValue)
			{
				
				String[] clm = trgStr.split(JACStrConst.COMMA);
				
				// 1つ目：割引サービスコード
				String wribSvcCd	= clm[0];
				
				// 2つ目：上限契約数
				String upplKeiCnt	= clm[1];
				
				String[] valStr = {wribSvcCd, upplKeiCnt};
				
				// 3つ目以降：料金グループコード
				for (int j = 2; clm.length > j; j++)
				{
					StringBuffer keyBuf = new StringBuffer();
					
					// （料金グループコード＋料金コースコード）
					keyBuf.append(workParmId);
					// 料金プランコード（右埋め空白12桁迄）
					keyBuf.append(JPCUtilCommon.fillHalfSpace(clm[j], JACStrConst.PRC_SVC_CD_LENGTH, true));
					
					String key = keyBuf.toString();
					
					// 既にある場合
					if (this.jdgMap.containsKey(key))
					{
						// マップから取り出したListを更新する。
						ArrayList<String[]> valList = this.jdgMap.get(key);
						valList.add(valStr);
					}
					// ない場合
					else
					{
						// Listを初期化し、マップに格納する。
						ArrayList<String[]> valList = new ArrayList<String[]>();
						valList.add(valStr);
						this.jdgMap.put(key, valList);
					}
				}
			}
		}
		
		
		assert 	JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][getWrbSvcTanka]");
	}
	
	/**
	 * 入力情報をもとに、割引適用上限判定マップ．キーを作成し、
	 * 返却します。
	 * 
	 * @param inMap 入力電文
	 * @return String 割引適用上限判定マップ．キー（料金グループコード＋料金コースコード＋料金サービスコード）
	 * @throws Exception 業務サービス内で発生した例外全般。
	 */
	private String makeMapKey(JBSbatServiceInterfaceMap inMap) throws Exception
	{
		StringBuffer buf = new StringBuffer();

		// 料金グループコード
		buf.append(inMap.getString(JBSbatACIFI015.PRC_GRP_CD));
		// 料金コースコード
		buf.append(inMap.getString(JBSbatACIFI015.PCRS_CD));
		// 料金サービスコード
		buf.append(inMap.getString(JBSbatACIFI015.PRC_SVC_CD));
		
		return buf.toString();
	}
	
	/**
	 * 休止判定
	 * @param  inMap   入力情報
	 * @return boolean 判定結果（true：休止中、false：休止でない）
	 * @throws Exception 業務サービス内で発生した例外全般。
	 */
	private boolean isPauseJudge(JBSbatServiceInterfaceMap inMap) throws Exception
	{
		assert 	JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][isPauseJudge]");
		
		String svcPauseDay		= inMap.getString(JBSbatACIFI015.SVC_PAUSE_DAY);		// サービス休止日
		String svcPauseRlsDay 	= inMap.getString(JBSbatACIFI015.SVC_PAUSE_RLS_YMD);	// サービス休止解除日

		assert 	JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][isPauseJudge][サービス休止日　　：" + svcPauseDay + "]");
		assert 	JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][isPauseJudge][サービス休止解除日：" + svcPauseRlsDay + "]");
		
		
		boolean rtn = false;	// 戻り値

		// サービス休止日、サービス休止解除日ともに未設定の場合
		if (svcPauseDay.equals(JACStrConst.KARA_MOJI) && svcPauseRlsDay.equals(JACStrConst.KARA_MOJI))
		{
			assert 	JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][isPauseJudge][サービス休止日、サービス休止解除日ともに未設定]");

			// 休止でない
			rtn = false;
		}
		// サービス休止日のみ設定されている場合
		else if (!svcPauseDay.equals(JACStrConst.KARA_MOJI) && svcPauseRlsDay.equals(JACStrConst.KARA_MOJI))
		{
			// サービス休止日 ≧ 初期処理．利用月翌月月初日 の場合
			if (svcPauseDay.compareTo(nextCycTukiSt) >= 0)
			{
				assert 	JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][isPauseJudge][サービス休止日のみ設定　かつ　サービス休止日 ≧ 利用月翌月月初日]");

				// 休止でない（予約分）
				rtn = false;
			}
			else
			{
				assert 	JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][isPauseJudge][サービス休止日のみ設定　かつ　サービス休止日 ＜ 利用月翌月月初日]");

				// 休止中
				rtn = true;
			}
		}
		// サービス休止日、サービス休止解除日ともに設定されている場合
		else if (!svcPauseDay.equals(JACStrConst.KARA_MOJI) && !svcPauseRlsDay.equals(JACStrConst.KARA_MOJI))
		{
			// サービス休止日 ≧ 初期処理．利用月翌月月初日 の場合
			if (svcPauseDay.compareTo(nextCycTukiSt) >= 0)
			{
				assert 	JACbatDebugLogUtil.printDebugLog(super.logPrint,
						"[L][isPauseJudge][サービス休止日、サービス休止解除日ともに設定あり　かつ　サービス休止日 ≧ 初期処理．利用月翌月月初日]");

				// 休止でない（予約分）
				rtn = false;
			}
			// サービス休止解除日 ≧ 初期処理で求めた利用月翌月月初日の場合
			else if (svcPauseRlsDay.compareTo(nextCycTukiSt) >= 0)
			{
				assert 	JACbatDebugLogUtil.printDebugLog(super.logPrint,
						"[L][isPauseJudge][サービス休止日、サービス休止解除日ともに設定あり　かつ　サービス休止解除日 ≧ 初期処理．利用月翌月月初日]");

				// 休止中（休止解除の予約あり）
				rtn = true;
			}
			else
			{
				assert 	JACbatDebugLogUtil.printDebugLog(super.logPrint,
						"[L][isPauseJudge][サービス休止日、サービス休止解除日ともに設定あり　かつ　サービス休止解除日 ＜ 初期処理．利用月翌月月初日]");

				// 休止中でない（休止解除）
				rtn = false;
			}
		}

		assert 	JACbatDebugLogUtil.printDebugLog(super.logPrint, "[L][isPauseJudge][判定結果：rtn = " + rtn + " ]");
		assert 	JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][isPauseJudge]");

		return rtn;
	}
	
	/**
	 * 出力情報編集
	 * @param  inMap      入力情報
	 * @param  value      {割引サービスコード, 上限契約数}
	 * @return outMap     出力情報
	 * @throws Exception  業務サービス内で発生した例外全般
	 */
	private JBSbatServiceInterfaceMap makeOutInfo(JBSbatServiceInterfaceMap inMap, String[] value) throws Exception
	{
		assert 	JACbatDebugLogUtil.printDebugLog(super.logPrint, "[S][makeOUtInfo]");
		
		JBSbatServiceInterfaceMap outMap = new JBSbatServiceInterfaceMap();
		
		outMap.set(JBSbatACIFM128.SEIKY_KEI_NO, 	inMap.get(JBSbatACIFI015.SEIKY_KEI_NO)); 	//   入力．請求先番号
		outMap.set(JBSbatACIFM128.SEIKY_YM, 		inMap.get(JBSbatACIFI015.SEIKY_YM)); 		//   入力．請求年月
		outMap.set(JBSbatACIFM128.WRIB_SVC_CD, 		value[0]); 									// 業パラ．割引サービスコード
		outMap.set(JBSbatACIFM128.SVC_NO, 			inMap.get(JBSbatACIFI015.SVC_NO)); 			//   入力．サービス番号
		outMap.set(JBSbatACIFM128.UPPL_KEI_CNT, 	value[1]); 									// 業パラ．上限契約数
		
		outMap.setOutFlg(true);

		assert 	JACbatDebugLogUtil.printDebugLog(super.logPrint, "[E][makeOUtInfo]");
		return outMap;
	}
}
