package jp.mosp.payroll.human.action;

import java.sql.SQLException;
import java.util.ArrayList;

import jp.mosp.common.CommonConst;
import jp.mosp.common.common.BaseVo;
import jp.mosp.common.common.MospConst;
import jp.mosp.common.common.MospException;
import jp.mosp.common.common.MospUtility;
import jp.mosp.human.action.HumanKihonCardAction;
import jp.mosp.legal.LegalConst;
import jp.mosp.payroll.base.PayrollConst;
import jp.mosp.payroll.dao.CmBankDao;
import jp.mosp.payroll.dao.CmBranchDao;
import jp.mosp.payroll.dao.CmCompanyDao;
import jp.mosp.payroll.dto.CmBankDto;
import jp.mosp.payroll.dto.CmBranchDto;
import jp.mosp.payroll.dto.CmCommutationDto;
import jp.mosp.payroll.dto.CmIncomeTaxDto;
import jp.mosp.payroll.dto.CmMidwayEnterDto;
import jp.mosp.payroll.dto.CmPaymentMeansDto;
import jp.mosp.payroll.dto.CmResidenceTaxDto;
import jp.mosp.payroll.dto.CmSocInsuranceDto;
import jp.mosp.payroll.dto.CmUnitAmountDto;
import jp.mosp.payroll.human.vo.HumanCalcVo;

/**
 * @author koike
 *
 */
public class HumanCalcAction extends PayrollHumanAction {
	
	// コマンド
	/**
	 * 
	 */
	public static final String	CMD_HUMAN_CALC_SELECT	= "U4150";
	
	/**
	 * 
	 */
	private static final String	CMD_HUMAN_CALC_INSERT	= "U4151";
	
	/**
	 * 
	 */
	private static final String	CMD_HUMAN_CALC_UPDATE	= "U4152";
	
	/**
	 * 
	 */
	public static final String	CMD_HUMAN_CALC_TAB		= "U4153";
	

	/**
	 * コンストラクタ
	 */
	public HumanCalcAction() {
		super();
	}
	
	/* (non-Javadoc)
	 * @see jp.mosp.common.common.BaseAction#getSpecificVo()
	 */
	@Override
	protected BaseVo getSpecificVo() {
		return new HumanCalcVo();
	}
	
	/**
	 * アクション
	 */
	public void action() throws Exception {
		// DBコネクション取得
		getConnection();
		// HUMAN権限確認
		confirmHumanAuth();
		// VO取得及び設定
		prepareVo();
		HumanCalcVo vo = (HumanCalcVo)getVo();
		// 銀行マスタ、支店マスタデータ作成
		convFinanceData(cfg.getProperty(MospConst.PPT_APP_DOCBASE) + PayrollConst.JS_FINANCE, false);
		// プルダウン設定
		setPulldown(vo);
		// メニューボタン設定
		setFunctionButton(false);
		// コマンド毎の処理
		if (cmd.equals(CMD_HUMAN_CALC_SELECT)) {
			// パラメータ取得
			vo.setParams(request);
			// ボタン内容設定
			setListButton();
			if (!vo.getTxtChangeKCode().equals("")) {
				// 表示(社員コードで情報を検索)
				select(vo);
			} else {
				setNextCmd("U4120");
			}
			vo.setMode(HumanCalcVo.MODE_INSERT);
			// セッションにDTOをセット
			//session.setAttribute(MospConst.ATT_DTO, aryDto);
		} else if (cmd.equals(CMD_HUMAN_CALC_INSERT)) {
			// パラメータ取得
			vo.setParams(request);
			// ボタン内容設定
			setListButton();
			// 更新
			regist(vo, false);
			// 検索
			select(vo);
			// セッションにDTOをセット
			//session.setAttribute(MospConst.ATT_DTO, aryDto);
		} else if (cmd.equals(CMD_HUMAN_CALC_UPDATE)) {
			// パラメータ取得
			vo.setParams(request);
			// ボタン内容設定
			setListButton();
			// 更新
			regist(vo, false);
			// 検索
			select(vo);
			// セッションにDTOをセット
			//session.setAttribute(MospConst.ATT_DTO, aryDto);
		} else if (cmd.equals(CMD_HUMAN_CALC_TAB)) {
			// パラメータ取得
			vo.setParams(request);
			// ボタン内容設定
			setListButton();
			// 情報設定
			vo.setHidCalcCurrentTab(key2);
			vo.setTxtChangeKCode(key1);
			// 表示(社員コードで情報を検索)
			select(vo);
		} else {
			throw new MospException(MospConst.EX_CMD_INVALID);
		}
	}
	
	/**
	 * プルダウン設定
	 * @param vo 対象VO
	 * @throws Exception 例外処理が発生した場合
	 */
	public void setPulldown(HumanCalcVo vo) throws Exception {
		// DBコネクション取得
		if (conn == null) {
			getConnection();
		}
		// プルダウン設定
		if (vo.aryPltCoBank != null) {
			return;
		}
		vo.aryPltEra = getCodeArray(PayrollConst.TID_JAPANESE);
		vo.aryPltShortYear = getYearArray(1, 0, PayrollConst.TIME_SHOWA_LONG);
		vo.aryPltMonth = getMonthArray();
		vo.aryPltDay = getDayArray();
		vo.aryPltCoBank = getCoBankArray();
		vo.aryPltAccountType = getCodeArray(PayrollConst.TID_ACCOUNT_TYPE);
		vo.aryPltPaymentMeans = getCodeArray(PayrollConst.TID_PAYMENT_MEANS);
		vo.aryPltAmountType = PayrollConst.getAmountTypeArray();
		vo.aryPltAmountTypeForRest = PayrollConst.getAmountTypeArrayForRest();
		vo.aryPltPaymentInterval = getCodeArray(PayrollConst.TID_PAY_INTERVAL);
		vo.aryPltLumpMonthlyType = getCodeArray(PayrollConst.TID_LUMP_TYPE);
		vo.aryPltPenDependentType = LegalConst.PENSION_INSURED_ARRAY;
		vo.aryPltIncomeTaxType = LegalConst.INCOME_TAX_ARRAY;
		vo.aryPltAdjustmentType = LegalConst.ADJUSTMENT_ARRAY;
		vo.aryPltHandicapType = LegalConst.HANDICAP_ARRAY;
		vo.aryPltWidowType = LegalConst.WIDOW_ARRAY;
		vo.aryPltStudentType = LegalConst.STUDENT_ARRAY;
		vo.aryPltSpouseIntendType = LegalConst.SPOUSE_INTEND_ARRAY;
		vo.aryPltLiveWithType = LegalConst.LIVE_WITH_ARRAY;
		vo.aryPltSpouseType = LegalConst.SPOUSE_ARRAY;
		vo.aryPltDependentType = LegalConst.DEPENDENT_ARRAY;
		vo.aryPltPensionType = LegalConst.PENSION_ARRAY;
		vo.aryPltParttimeType = LegalConst.PARTTIME_ARRAY;
		vo.aryPltEmployeeType = LegalConst.EMPLOYEE_ARRAY;
		vo.aryPltCalcInsType = LegalConst.CALC_INS_ARRAY;
		vo.aryPltNursingInsType = LegalConst.NURSING_INS_ARRAY;
		vo.aryPltCalcUnemployType = LegalConst.CALC_UNEMPLOY_ARRAY;
		vo.aryPltBonusHealthType = LegalConst.BONUS_HEALTH_ARRAY;
		vo.aryPltBounsPensionType = LegalConst.BONUS_PENSION_ARRAY;
		vo.aryPltHealthLostType = LegalConst.HEALTH_LOST_ARRAY;
		vo.aryPltPensionLostType = LegalConst.PENSION_LOST_ARRAY;
		vo.aryPltUnemployLostType = LegalConst.UNEMPLOY_LOST_ARRAY;
		vo.aryPltMidwayType = LegalConst.MIDWAY_ENTER_ARRAY;
		
		// 和暦設定取得
		vo.listConf = getConfList(PayrollConst.CONF_ID_JP_IMP_CAL);
		// JSに譲渡する配列設定
		//vo.setJSArray();
		
	}
	
	/**
	 * データ表示
	 * @param vo 対象VO
	 * @throws Exception 例外処理が発生した場合
	 */
	public void select(HumanCalcVo vo) throws Exception {
		// 表示(社員コードで情報を検索)
		// DBコネクション取得
		if (conn == null) {
			getConnection();
		}
		// 選択社員人事給与情報取得
		getSelectedEmployeeBasis();
		// 人事給与情報取得
		findHumanCalcInfo(vo.getEscLblKCode(), false);
		// 人事管理情報取得
		findHumanPersonnelInfo(vo.getEscLblKCode(), false);
		// 支給方法、口座名、フリガナ設定
		getHolderName(vo);
		// VO初期化
		vo.initFields();
		vo.setTxtChangeKCode(vo.getEscLblKCode());
		// 保険料率設定
		CmCompanyDao cmCompanyDao = new CmCompanyDao();
		cmCompanyDao.initDao(cfg, cmd, aspUser, user, conn);
		vo.setPremiumRatio(cmCompanyDao.findAll());
		// 人事情報設定
		vo.setFields(cmSocInsuranceDto, cmResidenceTaxDto, cmIncomeTaxDto, cmMidwayEnterDto, listPaymentMeans,
				listCommutation, listUnitAmount, aryUnitType);
		// 銀行名設定
		setFinanceName(vo);
		// 排他情報設定
		String editor = setExclusive(PayrollConst.EXC_HUMAN_CA_PE, user.getUserId(), vo.getEscLblKCode());
		if (editor != null) {
			addErrMessage(MospUtility.getMessage(msg, PayrollConst.MSG_EXCLUSIVE, editor));
		}
		setNeedExclusive(true);
	}
	
	/**
	 * データ挿入
	 * @param vo 対象VO
	 * @param isInsert 挿入フラグ
	 * @throws Exception 例外処理が発生した場合
	 */
	public void regist(HumanCalcVo vo, boolean isInsert) throws Exception {
		// DBコネクション取得
		if (conn == null) {
			getConnection();
		}
		// パラメータの妥当性確認
		vo.validate();
		// 人事基本情報取得
		getSelectedEmployeeBasis();
		// 人事給与情報取得
		findHumanCalcInfo(vo.getEscLblKCode(), true);
		// 存在確認
		if (isInsert) {
			//chkDuplicate(umBasisDao.findForKey(uhBasisDto.getKCode()), vo);
		}
		// DTO準備
		
		CmSocInsuranceDto upCmSocInsuranceDto = new CmSocInsuranceDto();
		CmResidenceTaxDto upCmResidenceTaxDto = new CmResidenceTaxDto();
		CmIncomeTaxDto upCmIncomeTaxDto = new CmIncomeTaxDto();
		CmMidwayEnterDto upCmMidwayEnterDto = new CmMidwayEnterDto();
		
		ArrayList<CmPaymentMeansDto> listUpPaymentMeans = new ArrayList<CmPaymentMeansDto>();
		ArrayList<CmCommutationDto> listUpCommutation = new ArrayList<CmCommutationDto>();
		ArrayList<CmUnitAmountDto> listUpUnitAmount = new ArrayList<CmUnitAmountDto>();
		
		vo.setDtoFields(upCmSocInsuranceDto, upCmResidenceTaxDto, upCmIncomeTaxDto, upCmMidwayEnterDto,
				listUpPaymentMeans, listUpCommutation, listUpUnitAmount);
		// 計算月確認
		/*
		if (!isAfterCalc(vo.getExpectedDate())) {
			String errMessage = MospUtility.getMessage(msg, UnicConst.MSG_APPLY_BEFORE_CALC, "");
			addErrMessage(errMessage);
			throw new MospException(UnicConst.EX_APPLY_BEFORE_CALC, errMessage);
		}
		*/
		// データ更新
		// 健康保険
		if (cmSocInsuranceDao.findForKey(upCmSocInsuranceDto.getKCode(), upCmSocInsuranceDto.getInsExpectedDate()) == null) {
			cmSocInsuranceDao.insert(upCmSocInsuranceDto);
		} else {
			// 登録内容チェック
			if (vo.checkInsuranceDtoFields(cmSocInsuranceDto, upCmSocInsuranceDto)) {
				// 排他処理
				cmSocInsuranceDao.findForUpdate(upCmSocInsuranceDto.getKCode());
				// 更新処理
				cmSocInsuranceDao.update(upCmSocInsuranceDto);
				
			}
		}
		// 住民税
		if (cmResidenceTaxDao.findForKey(upCmResidenceTaxDto.getKCode(), upCmResidenceTaxDto.getResExpectedDate()) == null) {
			cmResidenceTaxDao.insert(upCmResidenceTaxDto);
		} else {
			// 登録内容チェック
			if (vo.checkResidenceTaxDtoFields(cmResidenceTaxDto, upCmResidenceTaxDto)) {
				// 排他処理
				cmResidenceTaxDao.findForUpdate(upCmResidenceTaxDto.getKCode());
				// 更新処理
				cmResidenceTaxDao.update(upCmResidenceTaxDto);
			}
		}
		// 所得税
		if (cmIncomeTaxDao.findForKey(upCmIncomeTaxDto.getKCode(), upCmIncomeTaxDto.getIncExpectedDate()) == null) {
			cmIncomeTaxDao.insert(upCmIncomeTaxDto);
		} else {
			// 登録内容チェック
			if (vo.checkIncomeTaxDtoFields(cmIncomeTaxDto, upCmIncomeTaxDto)) {
				// 排他処理
				cmIncomeTaxDao.findForUpdate(upCmIncomeTaxDto.getKCode());
				// 更新処理
				cmIncomeTaxDao.update(upCmIncomeTaxDto);
			}
		}
		// 登録内容チェック
		if (vo.checkPaymentMeansDtoFields(listPaymentMeans, listUpPaymentMeans)) {
			// 支給方法
			// フリガナ、名義が社員名と同じでかつ、その他が空のデータは登録させない。
			listUpPaymentMeans = vo.chkRegistPaymentData(listUpPaymentMeans);
			// 既存支給方法削除
			cmPaymentMeansDao.deleteForEmployee(vo.getEscLblKCode());
			for (CmPaymentMeansDto cmPaymentMeansDto : listUpPaymentMeans) {
				cmPaymentMeansDao.insert(cmPaymentMeansDto);
			}
			
		}
		// 登録内容チェック
		if (vo.checkCommutationDtoFields(listCommutation, listUpCommutation)) {
			// 通勤手当
			cmCommutationDao.deleteForEmployee(vo.getEscLblKCode());
			for (CmCommutationDto cmCommutationDto : listUpCommutation) {
				cmCommutationDao.insert(cmCommutationDto);
			}
			
		}
		// 登録内容チェック
		if (vo.checkUnitAmountDtoFields(listUnitAmount, listUpUnitAmount)) {
			// 計算単価
			cmUnitAmountDao.deleteForEmployee(vo.getEscLblKCode());
			for (CmUnitAmountDto cmUnitAmountDto : listUpUnitAmount) {
				cmUnitAmountDao.insert(cmUnitAmountDto);
			}
		}
		
		// 中途入社
		if (cmMidwayEnterDao.findForKey(upCmMidwayEnterDto.getKCode()) == null) {
			cmMidwayEnterDao.insert(upCmMidwayEnterDto);
		} else {
			// 登録内容チェック
			if (vo.checkCmMidwayEnterDtoFields(cmMidwayEnterDto, upCmMidwayEnterDto)) {
				// 更新処理
				cmMidwayEnterDao.update(upCmMidwayEnterDto);
			}
		}
		
		// DTO再取得
		findHumanCalcInfo(vo.getEscLblKCode(), false);
		
		// コミット
		commit();
		// モード設定
		vo.setMode(HumanCalcVo.MODE_UPDATE);
		// メッセージ設定
		vo.setMessage(MospUtility.getMessage(msg, MospConst.MSG_INSERT, ""));
	}
	
	/**
	 * 口座名、フリガナ取得
	 * @param vo 対象VO
	 */
	protected void getHolderName(HumanCalcVo vo) {
		// 設定準備
		ArrayList<CmPaymentMeansDto> listAddPaymentMeans = new ArrayList<CmPaymentMeansDto>();
		for (int i = 0; i < PayrollConst.PAYMENT_MEANS_COUNT; i++) {
			// 支給方法リストが存在しない場合
			if (listPaymentMeans.size() == 0) {
				// DTOを初期化
				CmPaymentMeansDto cmPaymentMeansDto = setPaymentMeansData(vo, i);
				// リストに追加
				listAddPaymentMeans.add(cmPaymentMeansDto);
				continue;
			}
			// 取得したリスト
			for (int j = 0; j < listPaymentMeans.size(); j++) {
				CmPaymentMeansDto cmPaymentMeansDto = listPaymentMeans.get(j);
				// 連番と一致したらADDリストに設定
				if (i == cmPaymentMeansDto.getMeansSequence()) {
					// リストに追加
					listAddPaymentMeans.add(cmPaymentMeansDto);
					break;
				}
				// 最後まで一致しない場合は名義を追加したDTOを設定
				if (j == listPaymentMeans.size() - 1) {
					// DTOを初期化
					cmPaymentMeansDto = setPaymentMeansData(vo, i);
					// リストに追加
					listAddPaymentMeans.add(cmPaymentMeansDto);
				}
			}
		}
		// 設定を反映
		listPaymentMeans = listAddPaymentMeans;
	}
	
	/**
	 * 支給方法設定
	 * @param vo 対象VO
	 * @param idx 連番
	 * @return
	 */
	protected CmPaymentMeansDto setPaymentMeansData(HumanCalcVo vo, int idx) {
		// DTOを初期化
		CmPaymentMeansDto cmPaymentMeansDto = new CmPaymentMeansDto();
		cmPaymentMeansDto.setKCode(vo.getEscLblKCode());
		cmPaymentMeansDto.setMeansSequence(idx);
		cmPaymentMeansDto.setHolderName(vo.getEscLblKName());
		cmPaymentMeansDto.setHolderKana(vo.getEscLblKKana());
		cmPaymentMeansDto.setPaidBankCode("");
		cmPaymentMeansDto.setPaidBranchCode("");
		return cmPaymentMeansDto;
	}
	
	private void setFinanceName(HumanCalcVo vo) throws SQLException, IllegalAccessException, NoSuchFieldException {
		if (listPaymentMeans.size() == 0) {
			return;
		}
		// DAOの準備
		CmBankDao cmBankDao = new CmBankDao();
		cmBankDao.initDao(cfg, cmd, aspUser, user, conn);
		// DAOの準備
		CmBranchDao cmBranchDao = new CmBranchDao();
		cmBranchDao.initDao(cfg, cmd, aspUser, user, conn);
		vo.lblPaidBankName = new String[listPaymentMeans.size()];
		vo.lblPaidBranchName = new String[listPaymentMeans.size()];
		for (int i = 0; i < listPaymentMeans.size(); i++) {
			CmPaymentMeansDto cmPaymentMeansDto = listPaymentMeans.get(i);
			CmBankDto cmBankDto = cmBankDao.findForKey(cmPaymentMeansDto.getPaidBankCode());
			if (cmBankDto != null) {
				vo.lblPaidBankName[i] = cmBankDto.getBankName();
			} else {
				vo.lblPaidBankName[i] = cmPaymentMeansDto.getPaidBankCode();
			}
			CmBranchDto cmBranchDto = cmBranchDao.findForKey(cmPaymentMeansDto.getPaidBankCode(), cmPaymentMeansDto
				.getPaidBranchCode());
			if (cmBranchDto != null) {
				vo.lblPaidBranchName[i] = cmBranchDto.getBranchName();
			} else {
				vo.lblPaidBranchName[i] = cmPaymentMeansDto.getPaidBranchCode();
			}
			
		}
		
	}
	
	/**
	 * @param isNewData
	 * @return
	 */
	@Override
	protected String[][] getFunctionArray(boolean isNewData) {
		String[][] aryFunction = null;
		if (isNewData) {
			aryFunction = new String[][]{ { "btnNewData", HumanKihonCardAction.CMD_HUMAN_BASIS_SHOW,
				CommonConst.NAM_MAKE_NEW_DATA }, };
		} else {
			aryFunction = new String[][]{
				{ "btnBasic", HumanKihonCardAction.CMD_HUMAN_BASIS_SELECT, CommonConst.NAM_EDIT_HUMAN_BASIC },
				{ "btnKojin", HumanPersonalCardAction.CMD_HUMAN_PERSONAL_SELECT, CommonConst.NAM_EDIT_HUMAN_KOJIN },
				{ "btnCalc", "U4150", "給与情報編集" }, };
			
		}
		return aryFunction;
	}
}
