/*********************************************************************
* All Rights reserved,Copyright (c) K-Opticom
**********************************************************************
*＜プログラム内容＞
*   システム名      ：eo顧客基幹システム
*   モジュール名    ：DKW04605SFLogic
*   ソースファイル名：DKW04605SFLogic.java
*   作成者          ：富士通
*   日付            ：2011年05月10日
*＜機能概要＞
*   入荷読込画面のビューロジックです。
*＜修正履歴＞
*   バージョン  修正日       修正者      修正内容
*   v1.00.00    2011/05/10   FJ）植木    新規作成
*   v39.00.00   2018/09/14   FJ)黒田(耕)【ANK-3488-00-00】４KSTB（ACASチップ）導入対応
*   v50.00.00   2020/08/25   FJ)謝      【ANK-3738-00-00】【eo】機器の製造年月日・ロット番号管理対応
*
**********************************************************************/
package eo.web.webview.DKW04605SF;

import static com.fujitsu.futurity.web.x31.X31SWebLog.DEBUG_LOG;
import static eo.common.constant.JPCOnlineMessageConstant.EKB4590_KW;

import java.util.List;
import java.util.ArrayList;
import java.util.HashMap;

import com.fujitsu.futurity.web.x31.X31CWebConst;
import com.fujitsu.futurity.web.x31.X31SDataBeanAccess;
import com.fujitsu.futurity.web.x31.X31SDataBeanAccessArray;

import eo.common.constant.JDKStrConst;
import eo.common.constant.JPCModelConstant;
import eo.common.constant.JPCOnlineMessageConstant;
import eo.common.util.JDKCommonUtil;
import eo.common.util.JPCUtilCommon;
import eo.web.webview.JCCWebBusinessLogic;
import eo.web.webview.CommonInfoCF.CommonInfoCFConst;
import eo.web.webview.DKW04602SF.DKW04602SFConst;
import eo.web.webview.common.JCCScreenConst;
import eo.web.webview.common.JCCWebCommon;
import eo.web.webview.common.JDKScreenConst;
import eo.web.webview.common.JDKWebCommon;
import eo.web.webview.mapping.DKSV0063_DKSV0063OPDBMapper;
import eo.web.webview.mapping.DKSV0065_DKSV0065OPDBMapper;

/**
 * DKW04605のビューロジック
 * <BR>
 * @author 富士通
 */
public class DKW04605SFLogic extends JCCWebBusinessLogic
{

	/** シリアルバージョン */
	private static final long serialVersionUID = 6070468429144209446L;
	/** ファイルキー */
	private static final String SESSION_KEY_FILE = "fileKey";
	/** 検索件数取得キー（最大検索件数） */
	private static final String DKW04602_MAX_SHOW_CNT = "DKW04602_MAX_SHOW_CNT";
	/** レコード種別（ヘッダ） */
	private static final String RECORD_HEADER = "51";
	/** レコード種別（明細） */
	private static final String RECORD_DETAIL = "52";
	/** レコード種別（トレーラ） */
	private static final String RECORD_TRAILER = "53";
	/** レコード種別（製造番号なし） */
	private static final String RECORD_SEIZO_NO_NASHI = "54";
	/** 項目数（ヘッダ） */
	private static final int COLUMN_CNT_HEADER = 13;
	/** 項目数（明細） */
// ANK-3488-00-00 MOD START
//	private static final int COLUMN_CNT_DETAIL = 13;
// ANK-3738-00-00 MOD START
//	private static final int COLUMN_CNT_DETAIL = 14;
	private static final int COLUMN_CNT_DETAIL = 15;
// ANK-3738-00-00 MOD END
// ANK-3488-00-00 MOD END
	/** 項目数（トレーラ） */
	private static final int COLUMN_CNT_TRAILER = 2;
	/** 項目数（製造番号なし） */
	private static final int COLUMN_CNT_SEIZO_NO_NASHI = 14;
	/** 項目位置（メーカーコード）（0始まり） */
	private static final int COLUMN_POS_MAKER_CD = 4;
	/** 項目位置（ヘッダの型番号）（0始まり） */
	private static final int COLUMN_POS_HEADER_MODEL_CD = 7;
	/** 項目位置（ヘッダのメーカーコード）（0始まり） */
	private static final int COLUMN_POS_HEADER_MAKER_CD = 4;
	/** 項目位置（明細の型番号）（0始まり） */
	private static final int COLUMN_POS_DETAIL_MODEL_CD = 1;
	/** 項目位置（レコード件数）（0始まり） */
	private static final int COLUMN_POS_RECORD_CNT = 1;
	/** メッセージ：データの件数 */
	private static final String MSG_DATA_COUNT = "データの件数";
	/** メッセージ：%d件を超える */
	private static final String MSG_COUNT_OVER = "%d件を超える";
	/** メッセージ：入荷読込 */
	private static final String MSG_NYUKA_READ = "入荷読込";
	/** メッセージ：レコード種別 */
	private static final String MSG_RECORD_SBT = "レコード種別";
	/** メッセージ：トレーラ */
	private static final String MSG_TRAILER = "トレーラ";
	/** メッセージ：項目数 */
	private static final String MSG_COLUMN_COUNT = "項目数";
	/** メッセージ：メーカー(ファイルの基本情報) */
	private static final String MSG_MAKER_FILE_HEADER = "メーカー(ファイルの基本情報)";
	/** メッセージ：型番号(ファイルの明細情報) */
	private static final String MSG_MODEL_CD_FILE_DETAIL = "型番号(ファイルの明細情報)";
	/** メッセージ：メーカー(画面) */
	private static final String MSG_MAKER_SCREEN = "メーカー(画面)";
	/** メッセージ：レコード件数 */
	private static final String MSG_RECORD_CNT = "レコード件数";
	/** メッセージ：読み込んだ件数 */
	private static final String MSG_READED_RECORD_CNT = "読み込んだ件数";
	/** メッセージ：レコード構成 */
	private static final String MSG_RECORD_KOSEI = "レコード構成";
	/** メッセージ：テーブル名(メーカー) */
	private static final String MSG_TABLE_MAKER = "メーカー";
	/** メッセージ：項目名(メーカーコード) */
	private static final String MSG_KOMOKU_MAKER_CD = "メーカーコード";
	/** メッセージ：メーカー(DB検索結果) */
	private static final String MSG_MAKER_DB = "メーカー(DB検索結果)";
	/** メッセージ：型番号(DB検索結果) */
	private static final String MSG_MODEL_CD_DB = "型番号(DB検索結果)";
	/** メッセージ：レコード種別不正 */
	private static final String MSG_RECORD_SBT_NG = "レコード種別不正";
	
	/** サービス：ヘッダーチェック用サービスＩＤ */
	private static final String DKSV_HEADER = "DKSV0063";
	/** サービス：明細チェック用サービスＩＤ */
	private static final String DKSV_DETAIL = "DKSV0065";
	
	/**
	 * 初期表示を処理します。
	 * @author 富士通
	 * @return 成否
	 * @throws Exception 例外
	 */
	public boolean init() throws Exception
	{
		JCCWebCommon.getScreenInfo(this);

		return true;
	}

	/**
	 * 読込ボタン押下処理を行います。
	 * @author 富士通
	 * @return 成否
	 * @throws Exception 例外
	 */
	public boolean upload() throws Exception
	{
		ArrayList<HashMap<String, Object>>  fileInfoList  = JCCWebCommon.getFileInfoArray(this);
		
		if (fileInfoList.size() == 0)
		{
			setMessage(EKB4590_KW, "ファイル");
			return false;
		}
		
		// 共通のチェック処理の呼び出し
		if (!JDKWebCommon.isCommonFileUploaded(fileInfoList, this))
		{
			return false;
		}
		
		String file = getFileAsString(fileInfoList);

		if (!isValidColumns(file))
		{
			return false;
		}

		saveFileToSession(fileInfoList);

		setNextScreen(JCCScreenConst.SCREEN_ID_CCW00105, JCCScreenConst.SCREEN_NAME_CCW00105);
		return true;
	}

	/**
	 * ファイルの内容を文字列で取得します。
	 * @author 富士通
	 * @param fileInfoList
	 * @return ファイル内容
	 */
	@SuppressWarnings("unchecked")
	private String getFileAsString(ArrayList<HashMap<String, Object>>  fileInfoList)
	{
		HashMap fileInfoMap = fileInfoList.get(0);
		String renbanKey = fileInfoMap.get(SESSION_KEY_FILE).toString();

		byte[] fileByte = JCCWebCommon.getFile(this, renbanKey);

		DEBUG_LOG.debug(String.format("アップロードファイル連番=%s", renbanKey));

		return new String(fileByte);
	}

	/**
	 * ファイルの行毎に期待される項目数をチェックします。
	 * @author 富士通
	 * @param file 精査するファイル
	 * @return true:エラーなし false:エラーあり
	 */
	private boolean isValidColumns(String file)
	{
		int index = 0;
		String[] lines = file.split(JDKStrConst.LINE_SEPARATOR);

		String maxSearchCnt = JCCWebCommon.getSearchConst(DKW04602_MAX_SHOW_CNT);
		int iMaxSearchCnt = Integer.parseInt(maxSearchCnt, 10);

		String lineTop = "";
		String lineEnd = "";
		if (!JDKCommonUtil.isNull(lines))
		{
			lineTop = lines[0].replaceAll(JDKStrConst.DOUBLE_QUAT, "");
			lineEnd = lines[lines.length - 1].replaceAll(JDKStrConst.DOUBLE_QUAT, "");
		}

		int lineCnt = lines.length;
		if (!JDKCommonUtil.isNull(lines) && lineTop.startsWith(RECORD_HEADER))
		{
			lineCnt--;
		}
		if (!JDKCommonUtil.isNull(lines) && lineEnd.startsWith(RECORD_TRAILER))
		{
			lineCnt--;
		}

		if (lineCnt > iMaxSearchCnt)
		{
			setMessage(JPCOnlineMessageConstant.EKB0780_KW, 
					MSG_DATA_COUNT, 
					String.format(MSG_COUNT_OVER, iMaxSearchCnt), 
					MSG_NYUKA_READ);
			return false;
		}
		
		for (String line : lines)
		{
			if (!isValidColumn(line, ++index, lines.length))
			{
				return false;
			}
		}
		
		// DB関連のチェック
		if (!checkHeaderMakerCd(lines[0]))
		{
			return false;
		}
		
		if (!checkDetailMakerCd(lines))
		{
			return false;
		}
		
		return true;
	}

	/**
	 * 指定の文字列が指定の項目数ではない場合、メッセージを設定します。
	 * @author 富士通
	 * @param line 精査する文字列
	 * @param index lineの行数
	 * @param totalCnt 総件数
	 * @return true:エラーなし false:エラーあり
	 */
	private boolean isValidColumn(String line, int index, long totalCnt)
	{
		// 囲み文字を削除する
		line = line.replaceAll(JDKStrConst.DOUBLE_QUAT, "");
		
		Integer expect = columnExpectFor(line);
		if (expect == null)
		{
			setMessage(JPCOnlineMessageConstant.EKB0830_TW, 
					Integer.toString(index), 
					MSG_RECORD_SBT,
					MSG_RECORD_SBT_NG);
			return false;
		}

		String [] columns = JDKCommonUtil.splitAnycase(line, JDKStrConst.COMMA);

		if (columns.length != expect.intValue())
		{
			setMessage(JPCOnlineMessageConstant.EKB0830_TW, 
					Integer.toString(index),
					MSG_COLUMN_COUNT,
					Integer.toString(columns.length));
			return false;
		}

		// 画面のメーカー
		String makerCdInput = JDKWebCommon.getData(this, DKW04605SFConst.MAKER_CD);

		// ヘッダレコード又は製造番号なしレコードの場合
		if (line.startsWith(RECORD_HEADER) || line.startsWith(RECORD_SEIZO_NO_NASHI))
		{
			if (line.startsWith(RECORD_HEADER) && index != 1)
			{
				setMessage(JPCOnlineMessageConstant.EKB0830_TW, 
						Integer.toString(index),
						MSG_RECORD_SBT,
						MSG_RECORD_KOSEI);
				return false;
			}
//			if (line.startsWith(RECORD_SEIZO_NO_NASHI) && (index != 1 || index != totalCnt))
			if (line.startsWith(RECORD_SEIZO_NO_NASHI) && index != 1)
			{
				setMessage(JPCOnlineMessageConstant.EKB0830_TW, 
						Integer.toString(index),
						MSG_RECORD_SBT,
						MSG_RECORD_KOSEI);
				return false;
			}
			
			// トレーラで終了していない
			if (index == totalCnt)
			{
				setMessage(JPCOnlineMessageConstant.EKB0830_TW, 
						Integer.toString(index),
						MSG_RECORD_SBT,
						MSG_TRAILER);
				return false;
			}
			
			String makerCd = this.trimMoji(columns[COLUMN_POS_MAKER_CD], JDKStrConst.DOUBLE_QUAT);
			// 画面のメーカーコードとファイルのヘッダのメーカーコードが異なる場合
			if (!makerCdInput.equals(makerCd))
			{
				setMessage(JPCOnlineMessageConstant.EKB0620_NW, 
						String.format(MSG_MAKER_FILE_HEADER, index),
						MSG_MAKER_SCREEN);
				return false;
			}
			
		}
		else if (line.startsWith(RECORD_DETAIL))
		{
			if (index == 1 || index == totalCnt)
			{
				setMessage(JPCOnlineMessageConstant.EKB0830_TW, 
						Integer.toString(index),
						MSG_RECORD_SBT,
						MSG_RECORD_KOSEI);
				return false;
			}
		}
		else if (line.startsWith(RECORD_TRAILER))
		{
//			if (index <= 2 || index != totalCnt)
			if (index != totalCnt)
			{
				setMessage(JPCOnlineMessageConstant.EKB0830_TW, 
						Integer.toString(index),
						MSG_RECORD_SBT,
						MSG_RECORD_KOSEI);
				return false;
			}
			String recordCnt = this.trimMoji(columns[COLUMN_POS_RECORD_CNT], JDKStrConst.DOUBLE_QUAT);
			recordCnt = JPCUtilCommon.fillZero(recordCnt, 10, false);
			String cnt = JPCUtilCommon.fillZero("" + index, 10, false);
			// レコード件数と読み込んだ件数が不一致の場合
			if (!cnt.equals(recordCnt))
			{
				setMessage(JPCOnlineMessageConstant.EKB0620_NW, 
						MSG_RECORD_CNT,
						MSG_READED_RECORD_CNT);
				return false;
			}
		}

		return true;
	}

	/**
	 * ヘッダー部分のメーカーコードをチェックする
	 * @param fields ヘッダー
	 * @return true:正常終了 / false:異常終了
	 */
	@SuppressWarnings("unchecked")
	private boolean checkHeaderMakerCd(String line)
	{
		X31SDataBeanAccess bean = super.getServiceFormBean();
		X31SDataBeanAccess[] paramBean = {bean};

		// ユースケースID格納用マップを生成。
		HashMap paramMap = new HashMap();
		paramMap.put(X31CWebConst.TELEGRAM_INFO_USECASE_ID, DKSV_HEADER);

		// ファイルの内容を分解する
		String [] columns = JDKCommonUtil.splitAnycase(line, JDKStrConst.COMMA);
		for (int i=0; i< columns.length; i++)
		{
			columns[i] = columns[i].replaceAll(JDKStrConst.DOUBLE_QUAT, "");
		}

		// KEYの設定
		JDKWebCommon.setData(this, columns[COLUMN_POS_HEADER_MODEL_CD], DKW04605SFConst.KEY_TAKNKIKI_MODEL_CD);
		JDKWebCommon.setData(this, columns[COLUMN_POS_HEADER_MAKER_CD], DKW04605SFConst.KEY_MAKER_CD);

		// マッピングクラスのインスタンスを生成
		DKSV0063_DKSV0063OPDBMapper mapper = new DKSV0063_DKSV0063OPDBMapper();
		HashMap dataMap = new HashMap();
		mapper.setDKSV006301SC(paramBean, dataMap, JPCModelConstant.FUNC_CD_1);
		mapper.setDKSV006302SC(paramBean, dataMap, JPCModelConstant.FUNC_CD_1);

		HashMap outputMap = new HashMap();
		invokeService(paramMap, dataMap, outputMap);

		mapper.getDKSV006301SC(paramBean, outputMap);
		mapper.getDKSV006302SC(paramBean, outputMap);

		HashMap<String, Object> outMap = (HashMap<String, Object>)outputMap.get("DKSV006301SC");
		ArrayList kikiList = (ArrayList) outMap.get("taknkiki_model_list");
		
		// 指定機器のメーカーコードが取得出来なかった場合はエラーとする
		if (kikiList.size() == 0)
		{
			setMessage(JPCOnlineMessageConstant.EKB0300_KW, 
					MSG_TABLE_MAKER,
					MSG_KOMOKU_MAKER_CD);
			return false;
		}

		return true;
	}

	/**
	 * 明細部分のメーカーコードをチェックする
	 * @param fields ヘッダー
	 * @return true:正常終了 / false:異常終了
	 */
	@SuppressWarnings("unchecked")
	private boolean checkDetailMakerCd(String[] lines)
	{
		X31SDataBeanAccess bean = super.getServiceFormBean();
		X31SDataBeanAccess[] paramBean = {bean};

		// ユースケースID格納用マップを生成。
		HashMap paramMap = new HashMap();
		paramMap.put(X31CWebConst.TELEGRAM_INFO_USECASE_ID, DKSV_DETAIL);

		List<String> modelCds = new ArrayList<String>();
		for (String line: lines)
		{
			String [] columns = JDKCommonUtil.splitAnycase(line, JDKStrConst.COMMA);
			for (int i=0; i< columns.length; i++)
			{
				columns[i] = columns[i].replaceAll(JDKStrConst.DOUBLE_QUAT, "");
			}
			if (RECORD_DETAIL.equals(columns[0]))
			{
				modelCds.add(columns[COLUMN_POS_DETAIL_MODEL_CD]);
			}
		}
		
		// マッピングクラスのインスタンスを生成
		DKSV0065_DKSV0065OPDBMapper mapper = new DKSV0065_DKSV0065OPDBMapper();
		HashMap dataMap = new HashMap();
		mapper.setDKSV006501CC(paramBean, dataMap, modelCds, JPCModelConstant.FUNC_CD_1);

		HashMap outputMap = new HashMap();
		invokeService(paramMap, dataMap, outputMap);

		mapper.getDKSV006501CC(paramBean, outputMap);

		X31SDataBeanAccessArray list = bean.getDataBeanArray(DKW04605SFConst.MODEL_LIST);
		X31SDataBeanAccess subbean = list.getDataBean(0);
		
		// 型番号リスト(DB検索結果)に含まれるメーカーコードの件数
		int count = (Integer)subbean.sendMessage(DKW04605SFConst.MAKER_CD, X31CWebConst.DATABEAN_GET_COUNT);
		
		// ヘッダーの情報も件数に含まれているので、＋１をしている
		if ( count != modelCds.size() +1) 
		{
			// ファイルの明細件数と、データの取得件数が異なる場合は、存在しないデータが
			// 明細に含まれていたとして、エラーとする
			setMessage(JPCOnlineMessageConstant.EKB0620_NW, 
					MSG_MODEL_CD_FILE_DETAIL,
					MSG_MODEL_CD_DB);
			return false;
		}

		// 画面のメーカー
		String makerCdInput = JDKWebCommon.getData(this, DKW04605SFConst.MAKER_CD);
		for ( int i=0; i<count; i++)
		{
			String makerCd = subbean.sendMessageString(DKW04605SFConst.MAKER_TYPE_CD_02, X31CWebConst.DATABEAN_GET_VALUE, i);
			if (!makerCdInput.equals(makerCd))
			{
				// 画面のメーカーと明細のメーカー(DB検索結果)が異なる場合はエラーとする
				setMessage(JPCOnlineMessageConstant.EKB0620_NW, 
						MSG_MAKER_DB,
						MSG_MAKER_SCREEN);
				return false;
			}
		}
		
		return true;
	}
	
	private String getListData(String listName, String valueName)
	{
		return getListData(listName, valueName, 0);
	}
	
	private String getListData(String listName, String valueName, int index)
	{
		X31SDataBeanAccess bean = super.getServiceFormBean();

		X31SDataBeanAccess subbean = bean.getDataBeanArray(listName).getDataBean(index);
		return subbean.sendMessageString(valueName, X31CWebConst.DATABEAN_GET_VALUE, 0);
	}

	/**
	 * レコード種別毎に期待される項目数を取得します。
	 * @author 富士通
	 * @param line ファイル行
	 * @return 項目数
	 */
	private Integer columnExpectFor(String line)
	{
		line = line.replaceAll(JDKStrConst.DOUBLE_QUAT, "");

		if (line.startsWith(RECORD_HEADER))
		{
			return COLUMN_CNT_HEADER;
		}
		else if (line.startsWith(RECORD_DETAIL))
		{
			return COLUMN_CNT_DETAIL;
		}
		else if (line.startsWith(RECORD_TRAILER))
		{
			return COLUMN_CNT_TRAILER;
		}
		else if (line.startsWith(RECORD_SEIZO_NO_NASHI))
		{
			return COLUMN_CNT_SEIZO_NO_NASHI;
		}
		
		return null;
	}

	/**
	 * ファイル情報をセッションに保存します。
	 * @param fileInfoList
	 * @author 富士通
	 * @throws Exception 例外発生時
	 */
	@SuppressWarnings("unchecked")
	private void saveFileToSession(ArrayList<HashMap<String, Object>>  fileInfoList) throws Exception
	{
		HashMap paramMap = new HashMap();

		// アップロードファイルの連番を取得
		HashMap fileInfoMap = fileInfoList.get(0);
		String renbanKey = fileInfoMap.get(SESSION_KEY_FILE).toString();

		paramMap.put(DKW04602SFConst.FILE_RENBAN, renbanKey);

		// メーカー名と商品名の退避
		paramMap.put(DKW04602SFConst.MAKER_NM_02, getListData(DKW04605SFConst.MAKER_LIST, DKW04605SFConst.MAKER_TYPE_NM_01));
		paramMap.put(DKW04602SFConst.GOODS_NM_02, getListData(DKW04605SFConst.MODEL_LIST, DKW04605SFConst.GOODS_TYPE_NM_02));
		
		String parentScreenId = JCCWebCommon.getScreenId(this);
		if (JDKCommonUtil.isNull(parentScreenId))
		{
			parentScreenId = JDKScreenConst.SCREEN_ID_DKW04602 + "0PJP";
		}
		JCCWebCommon.setScreenInfo(this, parentScreenId, paramMap);

		DEBUG_LOG.debug(String.format("入荷データをセッションへ格納。paramMap=%s", paramMap));
	}

	/**
	 * メッセージを設定します。
	 * @author 富士通
	 * @param messageId メッセージＩＤ
	 * @param replacements 置換文字列
	 */
	private void setMessage(String messageId, String...replacements)
	{
		JCCWebCommon.setMessageInfo(this, messageId, replacements);
	}

	/**
	 * 画面遷移先を設定します。
	 * @author 富士通
	 * @param nextScreenId 遷移先画面ＩＤ
	 * @param nextScreenName 遷移先画面名
	 */
	private void setNextScreen(String nextScreenId, String nextScreenName)
	{
		X31SDataBeanAccess  commoninfoBean = super.getCommonInfoBean();
	
		commoninfoBean.sendMessageString(CommonInfoCFConst.NEXT_SCREEN_ID, X31CWebConst.DATABEAN_SET_VALUE, nextScreenId);
		commoninfoBean.sendMessageString(CommonInfoCFConst.NEXT_SCREEN_NAME, X31CWebConst.DATABEAN_SET_VALUE, nextScreenName);

		DEBUG_LOG.debug(String.format("%s(%s)へ遷移します", nextScreenName, nextScreenId));
	}

	/**
	 * 文字列前後のmojiのTrimを行います。
	 * <br>
	 * @param value 編集を行う文字列
	 * @param moji Trimしたい文字
	 * @return String 編集された文字列
	 */
	private String trimMoji(String value, String moji)
	{
		if (JDKCommonUtil.isNull(value))
		{
			return "";
		}

		StringBuffer arg0 = new StringBuffer(value);

		// 前方の空白（半角・全角）の削除
		while (arg0.substring(0, 1).equals(moji))
		{
			arg0.deleteCharAt(0);

			if (arg0.length() <= 0)
			{
				break;
			}
		}

		while (arg0.substring(arg0.length() - 1, arg0.length()).equals(moji))
		{
			arg0.deleteCharAt(arg0.length() - 1);

			if(JDKCommonUtil.isNull(arg0))
			{
				break;
			}
		}

		return arg0.toString();
	}
}
