/*
 * MosP - Mind Open Source Project         http://www.mosp.jp/
 * Copyright (C) 1987-2009 MIND Co., Ltd.  http://www.e-mind.co.jp/
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
package jp.mosp.payroll.common;

import java.sql.SQLException;
import java.util.Date;
import java.util.List;

//import jp.mosp.payroll.base.AttendanceTotalAction;
import jp.mosp.payroll.base.PayrollConst;
import jp.mosp.payroll.dao.BankTransferDao;
import jp.mosp.payroll.dao.CmBankDao;
import jp.mosp.payroll.dao.CmBranchDao;
import jp.mosp.payroll.dao.CmCoBankDao;
import jp.mosp.payroll.dao.CmCompanyDao;
import jp.mosp.payroll.dto.BankTransferFBDataDto;
import jp.mosp.payroll.dto.CmBankDto;
import jp.mosp.payroll.dto.CmBranchDto;
import jp.mosp.payroll.dto.CmCoBankDto;
import jp.mosp.payroll.dto.CmCompanyDto;
import jp.mosp.payroll.common.vo.FirmBankingOutputVo;
import jp.mosp.common.action.MosPAction;
import jp.mosp.common.common.MospConst;
import jp.mosp.common.common.MospException;
import jp.mosp.common.common.MospUtility;
import jp.mosp.legal.LegalReportUtility;

public class BonusFBDataOutputAction  extends MosPAction {
	// コマンド
	private static final String CMD_BONUS_FB_DATA_OUTPUT = "P9011";
	
	/**
	 * コンストラクタ
	 */
	public BonusFBDataOutputAction() {
		super();
		setNeedProcSeq(false);
	}
	
	int total  = 0;
	int amount = 0; 
	// 追加レコード長
	int lenRecord = 0;

	
	/**
	 * アクション
	 */
	public void action() throws Exception {
		// DBコネクション取得
		getConnection();
		// PAYROLL権限確認
		confirmPayrollAuth();
		// VOの取得
		FirmBankingOutputVo vo = (FirmBankingOutputVo)session.getAttribute(MospConst.ATT_FORMER_VO);
		vo.clearMessage();
		vo.clearErrField();
		vo.initVo(cfg, msg, cmd, aspUser, user);
		if (cmd.equals(CMD_BONUS_FB_DATA_OUTPUT)) {
			// パラメータ取得
			vo.setParams(request);
			// 会社情報登録
			updateCompanyInfo(vo);
			// 追加レコード長取得
			getAddRecordLength(Integer.parseInt(vo.getTxtRecordLength()));
			// 対象年月取得
			Date payday = vo.getDate(vo.getPltSpecifyYear(), vo.getPltSpecifyMonth(), vo.getPltSpecifyDay());
			Date targetMonth = vo.getDate(vo.getPltSpecifyYear(), vo.getPltSpecifyMonth(), String.valueOf(PayrollConst.TIME_DEFAULT_DAY));
			// FBデータ情報取得
			BankTransferDao bankTransferDao = new BankTransferDao();
			bankTransferDao.initDao(cfg, cmd, aspUser, user, conn);	
			// ステータスが確定の賞与データのみ取得
			List<BankTransferFBDataDto> list = bankTransferDao.findForCondition(vo.getPltCoBankCode(), targetMonth, payday, false);
			// 帳票作成準備
			StringBuffer sb = new StringBuffer();
			String fileName = vo.getPltSpecifyYear () + PayrollConst.FILE_NAME_SEPARATOR
							+ vo.getPltSpecifyMonth() + PayrollConst.FILE_NAME_SEPARATOR
							+ vo.getPltSpecifyDay  () + PayrollConst.FILE_NAME_SEPARATOR
							+ PayrollConst.FILE_FB_BONUS_DATA;
			request.setAttribute(MospConst.ATT_FILE_NAME, fileName);
			request.setAttribute(MospConst.ATT_FILE_OBJECT, sb);
			// 賞与データ確認
			if (list.size() == 0) {
				String errMessage = MospUtility.getMessage(msg, PayrollConst.MSG_NO_BONUS, "");
				sb.append(errMessage);
				return;
			}
			// FBデータ作成
			getFBDataRecord(sb, list, vo);
		}
	}
	

	
	/**
	 * FBデータ作成
	 * @param sb
	 * @param list
	 * @throws Exception
	 */
	protected void getFBDataRecord(StringBuffer sb, List<BankTransferFBDataDto> list, FirmBankingOutputVo vo)
		throws Exception
	{
		// 会社銀行情報取得準備
		CmCoBankDao cmCoBankDao = new CmCoBankDao();
		cmCoBankDao.initDao(cfg, cmd, aspUser, user, conn);
		// 会社銀行コードを持つ社員のリストを取得
		// 会社銀行情報取得
		CmCoBankDto	cmCoBankDto = cmCoBankDao.findForKey(vo.getPltCoBankCode());
		// 対象社員でまわす
		for (int j = 0; j < list.size(); j++) {
			BankTransferFBDataDto bankTransferFBDataDto = list.get(j);
			if (j == 0) {
				// ヘッダーレコード設定
				setHeaderRecordData(sb, bankTransferFBDataDto, cmCoBankDto, vo);
			}
			// データレコード設定
			setDataRecordData(sb, bankTransferFBDataDto, vo);
			// ステータス更新
			updateBonusStatus(bankTransferFBDataDto);
		}
		// すべて確認し終わったらトレーラーレコード設定
		LegalReportUtility.getTrailerRecord(sb, String.valueOf(total), String.valueOf(amount)
				, checkLineFeed(vo.getPltRecordType()), lenRecord);
		// 改行付与確認
		checkLineFeed(vo.getPltEndRecord());

		// エンドレコード作成
		// エンドレコード出力確認
		if (checkLineFeed(vo.getPltEndRecord())) {
			LegalReportUtility.getEndRecord(sb, checkLineFeed(vo.getPltRecordType()), lenRecord);
		}
		// 初期化
		total = 0;
		amount = 0;
	}
	
	/**
	 * ヘッダーデータ設定
	 * @param sb
	 * @param aryBankCode
	 * @param aryBranchCode
	 * @param cmCompanyDto
	 * @param udPaymentDto
	 * @param cmCoBankDto
	 * @throws Exception 
	 */
	protected void setHeaderRecordData(
			StringBuffer sb, BankTransferFBDataDto bankTransferFBDataDto,CmCoBankDto cmCoBankDto,
			FirmBankingOutputVo vo
	) throws Exception {
		
		String[] aryBankName   = getBankName(cmCoBankDto.getBankCode());
		String[] aryBranchName = getBranchNameArray(cmCoBankDto.getBankCode(),cmCoBankDto.getBranchCode());
		
		// 銀行名設定
		String coBankName   = aryBankName  [2];
		String coBranchName = aryBranchName[3];
		LegalReportUtility.getHeaderRecode(sb, PayrollConst.FB_BONUS_TYPE_CODE, vo.getPltCodeType(),
					vo.getTxtCompanyCode(), getLowerUpKana(vo.getTxtCompanyName())
					, String.valueOf(MospUtility.getMonth(bankTransferFBDataDto.getPayday())), String.valueOf(MospUtility.getDay(bankTransferFBDataDto.getPayday()))
					, cmCoBankDto.getBankCode   (), getLowerUpKana(coBankName)
					, cmCoBankDto.getBranchCode (), getLowerUpKana(coBranchName)
					, cmCoBankDto.getAccountType(), cmCoBankDto.getAccountNo()
					, checkLineFeed(vo.getPltRecordType()), lenRecord
			);
	}
	
	/**
	 * データレコードデータ設定
	 * @param sb
	 * @param bankTransferFBDataDto
	 * @throws Exception
	 */
	private void setDataRecordData(
		StringBuffer sb, BankTransferFBDataDto bankTransferFBDataDto, FirmBankingOutputVo vo
	) throws Exception {
		// 改行付与確認
		checkLineFeed(vo.getPltRecordType());
		
		
		String[] aryBankName   = getBankName(bankTransferFBDataDto.getPaidBankCode());
		String[] aryBranchName = getBranchNameArray(bankTransferFBDataDto.getPaidBankCode(),bankTransferFBDataDto.getPaidBranchCode());

		// 銀行名設定
		String bankName   = aryBankName  [2];
		String branchName = aryBranchName[3];
		String bankPayAmount = String.valueOf(bankTransferFBDataDto.getBankPayAmount());
		
		LegalReportUtility.getFBDataRecord(
			sb, bankTransferFBDataDto.getPaidBankCode(), getLowerUpKana(bankName)
			, bankTransferFBDataDto.getPaidBranchCode(), getLowerUpKana(branchName)
			, bankTransferFBDataDto.getAccountType(), bankTransferFBDataDto.getAccountNo()
			, getLowerUpKana(bankTransferFBDataDto.getHolderKana()) , bankPayAmount
			, bankTransferFBDataDto.getKCode(), bankTransferFBDataDto.getStationCode()
			, checkLineFeed(vo.getPltRecordType()), lenRecord
		);
		// 件数設定
		total ++;
		// 合計金額設定
		amount +=  bankTransferFBDataDto.getBankPayAmount();

		
	}
	
	/**
	 * 賞与ステータス更新
	 * @param bankTransferFBDataDto
	 * @throws SQLException
	 * @throws IllegalAccessException
	 * @throws NoSuchFieldException
	 * @throws MospException
	 */
	private void updateBonusStatus(BankTransferFBDataDto bankTransferFBDataDto)
		throws SQLException, IllegalAccessException, NoSuchFieldException, MospException
	{
		// 給与情報更新
	//	PhBounsDao phBonusDao = new PhBounsDao();
	//	phBonusDao.initDao(cfg, cmd, aspUser, user, conn);
	//	PhBounsDto udBonusDto = phBonusDao.findForKey(bankTransferFBDataDto.getKCode(), bankTransferFBDataDto.getCalcDate(), bankTransferFBDataDto.getPayday());
	//	if (udBonusDto != null) {
			// ステータスをFBデータ出力済みに設定
	//		udBonusDto.setCalcStatus(UnicConst.CALC_STATUS_FB);
			// UD_PAYMENT更新
	//		udBonusDao.update(udBonusDto, true);
			// コミット
	//		commit();
	//	}
		
	}
	
	/**
	 * 会社情報更新
	 * @param vo
	 * @throws SQLException
	 * @throws IllegalAccessException
	 * @throws NoSuchFieldException
	 * @throws MospException
	 */
	private void updateCompanyInfo(FirmBankingOutputVo vo) throws SQLException, IllegalAccessException, NoSuchFieldException, MospException {
		// DAO準備
		CmCompanyDao cmCompanyDao = new CmCompanyDao();
		cmCompanyDao.initDao(cfg, cmd, aspUser, user, conn);
		// 存在確認
		CmCompanyDto cmCompanyDto = cmCompanyDao.findAll();
		
		if (cmCompanyDto != null) {
			cmCompanyDto.setCompanyFbAddress(vo.getTxtCoAddress());
			cmCompanyDto.setCompanyFbKana(vo.getTxtCompanyName ());
			// 更新
			cmCompanyDao.update(cmCompanyDto);
		} else {
			cmCompanyDto = new CmCompanyDto();
			cmCompanyDto.setCompanyFbAddress(vo.getTxtCoAddress());
			cmCompanyDto.setCompanyFbKana(vo.getTxtCompanyName ());
			// 登録
			cmCompanyDao.insert(cmCompanyDto);
			
		}
		// コミット
		commit();
	}
	
	/**
	 * 銀行名取得(利用可能所属のみ)(CM_BANK)
	 * @return 銀行名リスト
	 * @throws Exception
	 */
	protected String[] getBankName(String bankCode) throws Exception {
		// 準備
		String[] aryBankName = new String[3];
		// DAOの準備
		CmBankDao dao = new CmBankDao();
		dao.initDao(cfg, cmd, aspUser, user, conn);
		// 情報の取得
		CmBankDto  cmBankDto = dao.findForKey(bankCode);
		// 配列の作成
		if (cmBankDto != null) {
			aryBankName[0] = cmBankDto.getBankCode();
			aryBankName[1] = cmBankDto.getBankName();
			aryBankName[2] = cmBankDto.getBankKana();
		} else {
			aryBankName[0] = bankCode;
			aryBankName[1] = bankCode;
			aryBankName[2] = bankCode;
			
		}
		
		return aryBankName;
	}
	
	/**
	 * 支店コード取得(利用可能所属のみ)(CM_BANK)
	 * @return 銀行コードリスト
	 * @throws Exception
	 */
	protected String[] getBranchNameArray(String bankCode, String branchCode) throws Exception {
		// 準備
		String[] aryBranchName = new String[4];
		// DAOの準備
		CmBranchDao dao = new CmBranchDao();
		dao.initDao(cfg, cmd, aspUser, user, conn);
		// 情報の取得
		CmBranchDto cmBranchDto = dao.findForKey(bankCode, branchCode);
		// 配列の作成
		if (cmBranchDto != null) {
			aryBranchName[0] = cmBranchDto.getBankCode();
			aryBranchName[1] = cmBranchDto.getBranchCode();
			aryBranchName[2] = cmBranchDto.getBranchName();
			aryBranchName[3] = cmBranchDto.getBranchKana();
		} else {
			aryBranchName[0] = bankCode;
			aryBranchName[1] = branchCode;
			aryBranchName[2] = branchCode;
			aryBranchName[3] = branchCode;
			
		}
		return aryBranchName;
	}
	
	/**
	 * 半角カナ変換(小文字→大文字)
	 * @param strTarget
	 * @return　半角カナ文字列
	 */
	protected String getLowerUpKana(String strTarget) {
		// 半角カナ(小文字)
		String[] aryLowerKana = {
				"ｧ",  "ｨ", "ｩ", "ｪ", "ｫ", "ｬ", "ｭ", "ｮ", "ｯ"
		};
		// 半角カナ(大文字)
		String[] aryLowerUpKana = {
				"ｱ",  "ｲ", "ｳ", "ｴ", "ｵ", "ﾔ", "ﾕ", "ﾖ", "ﾂ"
		};
		// 準備
		String retString = "";
		String repString = "";
		// 文字列の桁数で回す
		for (int i = 0; i < strTarget.length(); i++) {
			// 順番に文字列を取得していく
			repString = strTarget.substring(i, i+1);
			// 文字列を順番に確認
			for (int j = 0; j < aryLowerKana.length; j++) {
				// 半角かな(小文字)が存在したら大文字へ変換
				if (aryLowerKana[j].equals(repString)) {
					repString = aryLowerUpKana[j];
					break;
				}
			}
			// 文字列を結合
			retString += repString;
		}
		return retString;
	}
	
	/**
	 * 改行付与確認
	 * @param strLineFeed
	 * @return
	 */
	private boolean checkLineFeed(String strLineFeed) {
		// レコード区分に改行をつけない
		if (strLineFeed.equals(PayrollConst.FB_RECORD_TYPE_NONE)) {
			return false;
		}
		// レコード区分に改行をつける
		return true;
	}
	
	
	/**
	 * 追加レコード長取得
	 * @param addLenRecord
	 */
	private void getAddRecordLength(int addLenRecord) {
		// 追加レコード長-120(最小レコード長)
		 lenRecord = addLenRecord - PayrollConst.FB_LOWER_LEN_RECORD;
		 if (lenRecord < 0) {
			 lenRecord = 0;
		 }
	}
}
