/*********************************************************************
*   All Rights reserved,Copyright (c) K-Opticom
**********************************************************************
*＜プログラム内容＞
*   システム名      ：eo顧客基幹システム
*   モジュール名    ：JCHejbKRCKCommon
*   ソースファイル名：JCHejbKRCKCommon.java
*   作成者          ：富士通
*   日付            ：2011年11月01日
*＜機能概要＞
*   関連制約共通処理部品クラス
*＜修正履歴＞
*   バージョン  修正日      修正者      修正内容
*   v1.00.00    2011/11/01  富士通      新規作成
*   v5.00.00	2013/07/09  FJ) 林	   【LT-2013-0000260】未来月の請求は登録させない対応
*	v9.00.00	2014/06/02  FJ) 江森   【OM-2013-0005201】随時請求登録時の請求年月チェックを修正。
*
**********************************************************************/

package eo.ejb.common.entity;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.ParseException;
import java.util.Calendar;

import com.fujitsu.futurity.model.base.CAANConnectionMgr;
import com.fujitsu.futurity.model.base.CAANException;
import com.fujitsu.futurity.model.base.CAANJDBCUtil;
import com.fujitsu.futurity.model.base.CAANLog;
import com.fujitsu.futurity.model.base.CAANMsg;
import com.fujitsu.futurity.model.base.CAANRuntimeException;
import com.fujitsu.futurity.model.ejb.common.JSYejbConnection;
import com.fujitsu.futurity.model.ejb.common.JSYejbLog;
import com.fujitsu.futurity.model.ejb.common.StatusCodes;
import com.fujitsu.futurity.model.ejb.common.fw.AgentDispatchContext;

import eo.common.constant.JACStrConst;
import eo.common.util.JPCDateUtil;
import eo.ejb.cbm.cbmmsg.CH0501CBMMsg;
import eo.ejb.cbm.entity.CH0011ETMsg;
import eo.ejb.cbm.entity.CH0011LE;
import eo.ejb.cbm.entity.CH0051LE;
import eo.ejb.cbm.entity.CH0101LE;
import eo.ejb.cbm.entity.CH0501ETMsg;
import eo.ejb.common.JCHModelCommon;
import eo.ejb.common.JKKModelCommon;
import eo.ejb.common.JPCModelCommon;

public class JCHejbKRCKCommon {

	/** スキーマ名 */
	private String schemaName = null;

	/** スキーマ定義情報 */
	private Object[][] contents = null;

	/** テーブル名 */
	private String tableName = null;

	/** スキーマ定義情報の取得メソッド名 */
	private static final String GET_CONTENTS = "getContents";

	/** スキーマテーブル名の取得メソッド名 */
	private static final String GET_TABLE = "getTableName";

	/** 更新年月日時分秒項目名(英名) */
	private static final String UPD_DTM = "UPD_DTM";

	/**
	 * <p>
	 * 未来年月日判定処理を行います。
	 * ※年月日に加算不要な場合は加算年月日にnullを設定してください。
	 * </p>
	 * 
	 * @param inMsg     処理対象のメッセージキャリア
	 * @param inContext ディスパッチコンテキスト
	 * @param trgYmd    対象年月日
	 * @param addYear   加算年
	 * @param addMonth  加算月
	 * @param addDay    加算日
	 * @return          true:未来(同日含む)
	 *                   false:未来以外
	 */
	public static boolean isFutureYmd(CAANMsg inMsg, AgentDispatchContext inContext, 
			Object trgYmd, Object addYear, Object addMonth, Object addDay)
	{
		// ログ出力
		CAANLog.println(CAANLog.LEVEL_FW, "CALL: JCHejbKRCKCommon#isFutureYmd");
		
		JCHejbKRCKCommon jcKrck = new JCHejbKRCKCommon();
		
		// 対象年月日がnull、または8桁でない場合エラー
		if (trgYmd == null || trgYmd.toString().length() != 8)
		{
			throw new CAANRuntimeException();
		}
		
		// 運用日付を取得する
		String opeDate = JPCModelCommon.getOpeDate(inMsg, null);
		
		try
		{
			// 対象年月日をCalendar型にキャストする
			Calendar trgCal = jcKrck.toCalendar(trgYmd.toString());
			// 運用日付をCalendar型にキャストする
			Calendar opeCal = jcKrck.toCalendar(opeDate);
			
			// 運用日に指定された年月日数を加算する
			opeCal = jcKrck.addYmd(opeCal, addYear, addMonth, addDay);
			
			// 対象年月日と(加算した)運用日を比較
			if (opeCal.compareTo(trgCal) > 0)
			{
				// ログ出力
				CAANLog.println(CAANLog.LEVEL_FW, "END: JCHejbKRCKCommon#isFutureYmd");
				
				// 対象年月日が運用日より未来でなければfalseを返却
				return false;
			}
			
			// ログ出力
			CAANLog.println(CAANLog.LEVEL_FW, "END: JCHejbKRCKCommon#isFutureYmd");
			
			// 対象年月日が運用日より未来であればtrueを返却
			return true;
		}
		catch (NumberFormatException nfe)
		{
			throw new CAANRuntimeException(nfe);
		}
	}
	
	/**
	 * <p>
	 * 未来年月日判定処理を行います。(同日は未来)
	 * ※年月日に加算不要な場合は加算年月日にnullを設定してください。
	 * </p>
	 * 
	 * @param inMsg     処理対象のメッセージキャリア
	 * @param inContext ディスパッチコンテキスト
	 * @param trgYmd    対象年月日
	 * @param addYear   加算年
	 * @param addMonth  加算月
	 * @param addDay    加算日
	 * @return          true:未来(同日含まない)
	 *                   false:未来以外
	 */
	public static boolean isFutureYmd2(CAANMsg inMsg, AgentDispatchContext inContext, 
			Object trgYmd, Object addYear, Object addMonth, Object addDay)
	{
		// ログ出力
		CAANLog.println(CAANLog.LEVEL_FW, "CALL: JCHejbKRCKCommon#isFutureYmd");
		
		JCHejbKRCKCommon jcKrck = new JCHejbKRCKCommon();
		
		// 対象年月日がnull、または8桁でない場合エラー
		if (trgYmd == null || trgYmd.toString().length() != 8)
		{
			throw new CAANRuntimeException();
		}
		
		// 運用日付を取得する
		String opeDate = JPCModelCommon.getOpeDate(inMsg, null);
		
		try
		{
			// 対象年月日をCalendar型にキャストする
			Calendar trgCal = jcKrck.toCalendar(trgYmd.toString());
			// 運用日付をCalendar型にキャストする
			Calendar opeCal = jcKrck.toCalendar(opeDate);
			
			// 運用日に指定された年月日数を加算する
			opeCal = jcKrck.addYmd(opeCal, addYear, addMonth, addDay);
			
			// 対象年月日と(加算した)運用日を比較
			if (opeCal.compareTo(trgCal) >= 0)
			{
				// ログ出力
				CAANLog.println(CAANLog.LEVEL_FW, "END: JCHejbKRCKCommon#isFutureYmd");
				
				// 対象年月日が運用日より未来でなければfalseを返却
				return false;
			}
			
			// ログ出力
			CAANLog.println(CAANLog.LEVEL_FW, "END: JCHejbKRCKCommon#isFutureYmd");
			
			// 対象年月日が運用日より未来であればtrueを返却
			return true;
		}
		catch (NumberFormatException nfe)
		{
			throw new CAANRuntimeException(nfe);
		}
	}
	
	/**
	 * <p>
	 * 過去日判定処理を行います。
	 * ※年月日に減算不要な場合は減算年月日にnullを設定してください。
	 * </p>
	 * 
	 * @param inMsg     処理対象のメッセージキャリア
	 * @param inContext ディスパッチコンテキスト
	 * @param trgYmd    対象年月日
	 * @param addYear   減算年
	 * @param addMonth  減算月
	 * @param addDay    減算日
	 * 
	 * @return          true:過去(同日含む)
	 *                   false:過去以外
	 */
	public static boolean isPastYmd(CAANMsg inMsg, AgentDispatchContext inContext, 
			Object trgYmd, Object subYear, Object subMonth, Object subDay)
	{
		// ログ出力
		CAANLog.println(CAANLog.LEVEL_FW, "CALL: JCHejbKRCKCommon#isPastYmd");
		
		JCHejbKRCKCommon jcKrck = new JCHejbKRCKCommon();

		// 対象年月日がnull、または8桁でない場合エラー
		if (trgYmd == null || trgYmd.toString().length() != 8)
		{
			throw new CAANRuntimeException();
		}
		
		// 運用日付を取得する
		String opeDate = JPCModelCommon.getOpeDate(inMsg, null);
		
		try
		{
			// 対象年月日をCalendar型にキャストする
			Calendar trgCal = jcKrck.toCalendar(trgYmd.toString());
			// 運用日付をCalendar型にキャストする
			Calendar opeCal = jcKrck.toCalendar(opeDate);
			
			// 運用日に指定された年月日数を減算する
			opeCal = jcKrck.subYmd(opeCal, subYear, subMonth, subDay);
			
			// 対象年月日と(減算した)運用日を比較
			if (opeCal.compareTo(trgCal) < 0)
			{
				// ログ出力
				CAANLog.println(CAANLog.LEVEL_FW, "END: JCHejbKRCKCommon#isPastYmd");
				
				// 対象年月日が運用日より過去でなければfalseを返却
				return false;
			}
			
			// ログ出力
			CAANLog.println(CAANLog.LEVEL_FW, "END: JCHejbKRCKCommon#isPastYmd");
			
			// 対象年月日が運用日より過去であればtrueを返却
			return true;
		}
		catch (NumberFormatException nfe)
		{
			throw new CAANRuntimeException(nfe);
		}
	}
	
	/**
	 * <p>
	 * 過去日判定処理を行います。
	 * ※年月日に減算不要な場合は減算年月日にnullを設定してください。
	 * </p>
	 * 
	 * @param inMsg     処理対象のメッセージキャリア
	 * @param inContext ディスパッチコンテキスト
	 * @param trgYmd    対象年月日
	 * @param addYear   減算年
	 * @param addMonth  減算月
	 * @param addDay    減算日
	 * 
	 * @return          true:過去(同日含まない)
	 *                   false:過去以外
	 */
	public static boolean isPastYmd2(CAANMsg inMsg, AgentDispatchContext inContext, 
			Object trgYmd, Object subYear, Object subMonth, Object subDay)
	{
		// ログ出力
		CAANLog.println(CAANLog.LEVEL_FW, "CALL: JCHejbKRCKCommon#isPastYmd");
		
		JCHejbKRCKCommon jcKrck = new JCHejbKRCKCommon();

		// 対象年月日がnull、または8桁でない場合エラー
		if (trgYmd == null || trgYmd.toString().length() != 8)
		{
			throw new CAANRuntimeException();
		}
		
		// 運用日付を取得する
		String opeDate = JPCModelCommon.getOpeDate(inMsg, null);
		
		try
		{
			// 対象年月日をCalendar型にキャストする
			Calendar trgCal = jcKrck.toCalendar(trgYmd.toString());
			// 運用日付をCalendar型にキャストする
			Calendar opeCal = jcKrck.toCalendar(opeDate);
			
			// 運用日に指定された年月日数を減算する
			opeCal = jcKrck.subYmd(opeCal, subYear, subMonth, subDay);
			
			// 対象年月日と(減算した)運用日を比較
			if (opeCal.compareTo(trgCal) <= 0)
			{
				// ログ出力
				CAANLog.println(CAANLog.LEVEL_FW, "END: JCHejbKRCKCommon#isPastYmd");
				
				// 対象年月日が運用日より過去でなければfalseを返却
				return false;
			}
			
			// ログ出力
			CAANLog.println(CAANLog.LEVEL_FW, "END: JCHejbKRCKCommon#isPastYmd");
			
			// 対象年月日が運用日より過去であればtrueを返却
			return true;
		}
		catch (NumberFormatException nfe)
		{
			throw new CAANRuntimeException(nfe);
		}
	}
	
	/**
	 * <p>
	 * 対象年月日と運用日付が同じ年月かチェックを行います。
	 * </p>
	 * 
	 * @param inMsg     処理対象のメッセージキャリア
	 * @param inContext ディスパッチコンテキスト
	 * @param trgYmd    対象年月日
	 * 
	 * @return          true:一致する
	 *                   false:一致しない
	 */
	public static boolean isSameYm(CAANMsg inMsg, AgentDispatchContext inContext, Object trgYmd)
	{
		// ログ出力
		CAANLog.println(CAANLog.LEVEL_FW, "CALL: JCHejbKRCKCommon#isSameYm");
		
		// 対象年月日がnull、または8桁でない場合エラー
		if (trgYmd == null || trgYmd.toString().length() != 8)
		{
			throw new CAANRuntimeException();
		}
		
		// 運用日付を取得
		String opeDate = JPCModelCommon.getOpeDate(inMsg, null);
		
		// 取得した運用日付、対象年月日を年月として6文字取得する
		String opeYm = opeDate.substring(0, 6);
		String trgYm = trgYmd.toString().substring(0, 6);
		
		// 取得した運用年月、対象年月が一致するか比較
		if (!opeYm.equals(trgYm))
		{
			// ログ出力
			CAANLog.println(CAANLog.LEVEL_FW, "END: JCHejbKRCKCommon#isSameYm");
			
			// 一致しなければfalseを返却
			return false;
		}
		
		// ログ出力
		CAANLog.println(CAANLog.LEVEL_FW, "END: JCHejbKRCKCommon#isSameYm");
		
		// 一致したらtrueを返却
		return true;
	}
	
	/**
	 * <p>
	 * 対象年月がスケジュール定義請求年月より未来かチェックを行います。
	 * </p>
	 * 
	 * @param inMsg     処理対象のメッセージキャリア
	 * @param inContext ディスパッチコンテキスト
	 * @param trgYm     対象年月
	 * 
	 * @return          true:未来
	 *                   false:未来でない
	 */
	public static boolean isFutureYm(CAANMsg inMsg, AgentDispatchContext inContext, Object trgYm)
	{
		// ログ出力
		CAANLog.println(CAANLog.LEVEL_FW, "CALL: JCHejbKRCKCommon#isFutureYm");

		boolean bRtn = true;

		Connection con1 = null;
		PreparedStatement pstmt = null;
		ResultSet rsltQuery = null;

		try
		{
			con1 = JSYejbConnection.getConnection(CH0501ETMsg.getTableName());

			StringBuffer sql_Buff = new StringBuffer();
			sql_Buff.append("SELECT ")
					.append("     CH0501.SEIKY_YM ")
					.append("  FROM ")
					.append("     CH_M_PRC_SCHDL_TEIGI CH0501 ")
					.append(" WHERE ")
					.append("     CH0501.EVENT_CD = ? ")
					.append(" AND CH0501.EVENT_YMD = ")
					.append("     (SELECT ")
					.append("           MIN(EVENT_YMD) ")
					.append("        FROM ")
					.append("           CH_M_PRC_SCHDL_TEIGI CH0501 ")
					.append("       WHERE ")
					.append("             EVENT_YMD >= ? ")
					.append("         AND EVENT_CD = ? ")
					.append("         AND MK_FLG = '0' ) ")
					.append(" AND CH0501.MK_FLG = '0' ");

			pstmt = con1.prepareStatement(sql_Buff.toString());

			JSYejbLog.outlog(inContext, JSYejbLog.DBACCESS, JCHejbKRCKCommon.class, sql_Buff);

			CAANJDBCUtil.setParam(pstmt, 1, JACStrConst.EVENT_CD_KAIK_SHORI_YMD);
			CAANJDBCUtil.setParam(pstmt, 2, JPCModelCommon.getOpeDate(inMsg, inContext, null));
			CAANJDBCUtil.setParam(pstmt, 3, JACStrConst.EVENT_CD_KAIK_SHORI_YMD);

			rsltQuery = pstmt.executeQuery();

			if (rsltQuery.next())
			{
				String seikyYm = rsltQuery.getString("SEIKY_YM");
				if (trgYm.toString().compareTo(seikyYm) <= 0)
				{
					// 対象年月がスケジュール定義請求年月より過去年月の場合、false
					bRtn = false;
				}
			}
		}
		catch (SQLException e)
		{
			inMsg.set(CH0501CBMMsg.STATUS, StatusCodes.FIND_DB_ERR);
			throw new CAANRuntimeException(e);
		}
		finally
		{
			try
			{
				if (rsltQuery != null)
				{
					rsltQuery.close();
				}
				if (pstmt != null)
				{
					pstmt.close();
				}
				if (con1 != null)
				{
					CAANConnectionMgr.getInstance().close(con1);
				}
			}
			catch(SQLException e)
			{
				inMsg.set(CH0501ETMsg.STATUS, StatusCodes.FIND_DB_ERR);
				throw new CAANRuntimeException(e);
			}
		}

		// ログ出力
		CAANLog.println(CAANLog.LEVEL_FW, "END: JCHejbKRCKCommon#isFutureYm");

		return bRtn;
	}

	/**
	/**
	 * <p>
	 * String型の日付をCalendar型にキャストする
	 * </p>
	 * 
	 * @param date キャストする日付
	 * 
	 * @return Calndar型にキャストしたdate
	 * @throws NumberFormatException 数値に変換できない場合にスローされる
	 */
	private Calendar toCalendar(Object date) throws NumberFormatException
	{
		// パラメータの日付を年、月、日に分割する
		int year = Integer.parseInt(date.toString().substring(0, 4));
		int month = Integer.parseInt(date.toString().substring(4, 6));
		int day = Integer.parseInt(date.toString().substring(6, 8));
		
		// カレンダーオブジェクト生成
		Calendar cal = Calendar.getInstance();
		// カレンダーオブジェクトを未設定にする
		cal.clear();
		
		// 分割したパラメータを設定する(月は0から始まるため、-1する)
		cal.set(Calendar.YEAR, year);
		cal.set(Calendar.MONTH, month -1);
		cal.set(Calendar.DATE, day);
		
		return cal;
	}
	
	/**
	 * パラメータに指定された日付を加算します。
	 * 
	 * @param cal      加算される日付
	 * @param addYear  加算する年数
	 * @param addMonth 加算する月数
	 * @param addDay   加算する日数
	 * 
	 * @return パラメータの値が加算されたcal
	 */
	private Calendar addYmd(Calendar cal, Object addYear, Object addMonth, Object addDay) throws NumberFormatException
	{
		// 運用日付にパラメータの年月日数を加算する
		// 年数が設定されていたら年数を加算する
		if (addYear != null && addYear.toString().length() > 0)
		{
			cal.add(Calendar.YEAR, Integer.parseInt(addYear.toString()));
		}
		// 月数が設定されていたら月数を加算する
		if (addMonth != null && addMonth.toString().length() > 0)
		{
			cal.add(Calendar.MONTH, Integer.parseInt(addMonth.toString()));
		}
		// 日数が設定されていたら日数を加算する
		if (addDay != null && addDay.toString().length() > 0)
		{
			cal.add(Calendar.DATE, Integer.parseInt(addDay.toString()));
		}
		
		return cal;
	}
	
	/**
	 * パラメータに指定された日付を減算します。
	 * 
	 * @param cal      減算される日付
	 * @param addYear  減算する年数
	 * @param addMonth 減算する月数
	 * @param addDay   減算する日数
	 * 
	 * @return パラメータの値が減算されたcal
	 */
	private Calendar subYmd(Calendar cal, Object addYear, Object addMonth, Object addDay) throws NumberFormatException
	{
		// 運用日付にパラメータの年月日数を減算する
		// 年数が設定されていたら年数を減算する(減算するため-1を掛ける)
		if (addYear != null && addYear.toString().length() > 0)
		{
			cal.add(Calendar.YEAR, Integer.parseInt(addYear.toString()) * -1);
		}
		// 月数が設定されていたら月数を減算する
		if (addMonth != null && addMonth.toString().length() > 0)
		{
			cal.add(Calendar.MONTH, Integer.parseInt(addMonth.toString()) * -1);
		}
		// 日数が設定されていたら日数を減算する
		if (addDay != null && addDay.toString().length() > 0)
		{
			cal.add(Calendar.DATE, Integer.parseInt(addDay.toString()) * -1);
		}
		
		return cal;
	}

	/**
	 * タイムスタンプチェックを行います。
	 * <br>
	 * @param inMsg 処理対象のメッセージキャリア
	 * @param schemaID スキーマID
	 * @return データが存在する場合はtrue、存在しない場合はfalse
	 */
	public static boolean isNotUpdated(CAANMsg inMsg, AgentDispatchContext inContext, String schemaID)
	{
		if (null == inMsg)
		{
			throw new IllegalArgumentException("inMsgの値が不正です。");
		}

		try
		{
			CAANMsg[] result = null;

			if ("CH0011".equals(schemaID))
			{
				CAANMsg searchMsg = new CAANMsg(CH0011ETMsg.class.getName());
				searchMsg.set(CH0011ETMsg.SAIKEN_NO, inMsg.getString(CH0011ETMsg.SAIKEN_NO));
				searchMsg.set(CH0011ETMsg.SAIKEN_YM, inMsg.getString(CH0011ETMsg.SAIKEN_YM));

				CH0011LE le = new CH0011LE();
				result = le.findByCondition(searchMsg);
			}
			else if ("CH0051".equals(schemaID))
			{
				CH0051LE le = new CH0051LE();
				result = le.findByCondition(inMsg);
			}
			else if ("CH0101".equals(schemaID))
			{
				CH0101LE le = new CH0101LE();
				result = le.findByCondition(inMsg);
			}

			if (result.length == 0)
			{
				// レコードが存在しない場合
				return false;
			}

			if (Long.parseLong(inMsg.getString(UPD_DTM)) < Long.parseLong(result[0].getString(UPD_DTM)))
			{
				return false;
			}
		}
		catch (CAANException ce)
		{
			// レコードが存在しない場合
			return false;
		}

		return true;
	}

	/**
	 * <p>
	 * 指定された請求年月が随時請求処理に適するかどうかチェックします。
	 * </p>
	 * 
	 * @param inMsg     処理対象のメッセージキャリア
	 * @param inContext ディスパッチコンテキスト
	 * @param trgYm     対象年月
	 * 
	 * @return [true:正常、false:異常]
	 */
	public static boolean chkSeikyYmForZuiji(CAANMsg inMsg, AgentDispatchContext inContext, Object trgYm)
	{
		// ログ出力
		CAANLog.println(CAANLog.LEVEL_FW, "CALL: JCHejbKRCKCommon#chkSeikyYmForZuiji");

		boolean bRtn = true;

		// 請求年月
		String seikyYm = trgYm.toString();

		// 料金スケジュール定義を取得
		CAANMsg[] prcScdl = JCHModelCommon.getPrcSchdlContain(inMsg, inContext, JACStrConst.EVENT_CD_KAIK_SHORI_YMD);

		// 次回請求年月
		String nextSeikyYm = "";

		// 1件のみ取得できる（次回請求年月）
		if (prcScdl.length > 0)
		{
			nextSeikyYm = prcScdl[0].getString(CH0501ETMsg.SEIKY_YM);
		}

		// 前回請求年月
		String preSeikyYm = "";
		
		if (!nextSeikyYm.equals(""))
		{
			String nSeikyYm = nextSeikyYm.concat("01");
			
			try {
				preSeikyYm = JPCDateUtil.addMonth(nSeikyYm, -1).substring(0, 6);
			} catch (ParseException e) {
				// TODO 自動生成された catch ブロック
				e.printStackTrace();
			}
		}

		// 指定された請求年月がオンライン運用日付基準の次回請求年月と同じではない場合、かつ
		// オンライン運用日付基準の前回請求年月と同じではない場合、エラー
		if (!seikyYm.equals(nextSeikyYm) && !seikyYm.equals(preSeikyYm))
		{
			bRtn = false;
		}

		// ログ出力
		CAANLog.println(CAANLog.LEVEL_FW, "END: JCHejbKRCKCommon#chkSeikyYmForZuiji");

		return bRtn;
	}

}
