package jp.mosp.payroll.human.action;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.sql.SQLException;
import java.util.Date;
import java.util.List;

import jp.mosp.common.common.MospConst;
import jp.mosp.kintai.common.action.MosPHumanAction;
import jp.mosp.payroll.base.Payment;
import jp.mosp.payroll.base.PayrollAction;
import jp.mosp.payroll.base.PayrollConst;
import jp.mosp.payroll.dao.CmBankDao;
import jp.mosp.payroll.dao.CmBranchDao;
import jp.mosp.payroll.dao.CmCoBankDao;
import jp.mosp.payroll.dao.CmCommutationDao;
import jp.mosp.payroll.dao.CmIncomeTaxDao;
import jp.mosp.payroll.dao.CmMidwayEnterDao;
import jp.mosp.payroll.dao.CmPaymentMeansDao;
import jp.mosp.payroll.dao.CmResidenceTaxDao;
import jp.mosp.payroll.dao.CmSocInsuranceDao;
import jp.mosp.payroll.dao.CmUnitAmountDao;
import jp.mosp.payroll.dao.PmDetailPaDao;
import jp.mosp.payroll.dao.PmDetailPbDao;
import jp.mosp.payroll.dao.PmDetailPdDao;
import jp.mosp.payroll.dao.PmDetailPsDao;
import jp.mosp.payroll.dao.PmDetailPtDao;
import jp.mosp.payroll.dto.CmBankDto;
import jp.mosp.payroll.dto.CmBranchDto;
import jp.mosp.payroll.dto.CmCoBankDto;
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.dto.PhPaymentDto;

public abstract class PayrollHumanAction extends MosPHumanAction {
	
	// フィールド
	protected String[][]				aryUnitType;
	
	protected CmPaymentMeansDao			cmPaymentMeansDao;
	protected List<CmPaymentMeansDto>	listPaymentMeans;
	protected CmPaymentMeansDto			cmPaymentMeansDto;
	protected CmCommutationDao			cmCommutationDao;
	protected List<CmCommutationDto>	listCommutation;
	protected CmCommutationDto			cmCommutationDto;
	protected CmResidenceTaxDao			cmResidenceTaxDao;
	protected List<CmResidenceTaxDto>	listCmResidenceTax;
	protected CmResidenceTaxDto			cmResidenceTaxDto;
	protected CmIncomeTaxDao			cmIncomeTaxDao;
	protected CmIncomeTaxDto			cmIncomeTaxDto;
	protected List<CmIncomeTaxDto>		listCmIncomeTax;
	protected CmUnitAmountDao			cmUnitAmountDao;
	protected List<CmUnitAmountDto>		listUnitAmount;
	protected CmUnitAmountDto			cmUnitAmountDto;
	protected CmSocInsuranceDao			cmSocInsuranceDao;
	protected CmSocInsuranceDto			cmSocInsuranceDto;
	
	protected CmMidwayEnterDao			cmMidwayEnterDao;
	protected CmMidwayEnterDto			cmMidwayEnterDto;
	
	protected List<CmSocInsuranceDto>	listCmSocInsurance;
	

	/**
	 * コンストラクタ
	 */
	protected PayrollHumanAction() {
		super();
		setCheckAuth(false);
	}
	
	/**
	 * 人事給与情報取得
	 * @param kCode       社員コード
	 * @param isForUpdate アップデート用フラグ
	 * @throws NoSuchFieldException
	 * @throws IllegalAccessException
	 * @throws SQLException
	 */
	protected void findHumanCalcInfo(String kCode, boolean isForUpdate) throws SQLException, IllegalAccessException,
			NoSuchFieldException {
		// 人事給与情報用DAO準備
		cmPaymentMeansDao = new CmPaymentMeansDao();
		cmPaymentMeansDao.initDao(cfg, cmd, aspUser, user, conn);
		cmCommutationDao = new CmCommutationDao();
		cmCommutationDao.initDao(cfg, cmd, aspUser, user, conn);
		cmResidenceTaxDao = new CmResidenceTaxDao();
		cmResidenceTaxDao.initDao(cfg, cmd, aspUser, user, conn);
		cmIncomeTaxDao = new CmIncomeTaxDao();
		cmIncomeTaxDao.initDao(cfg, cmd, aspUser, user, conn);
		cmUnitAmountDao = new CmUnitAmountDao();
		cmUnitAmountDao.initDao(cfg, cmd, aspUser, user, conn);
		cmSocInsuranceDao = new CmSocInsuranceDao();
		cmSocInsuranceDao.initDao(cfg, cmd, aspUser, user, conn);
		
		cmMidwayEnterDao = new CmMidwayEnterDao();
		cmMidwayEnterDao.initDao(cfg, cmd, aspUser, user, conn);
		
		// 現在の情報を取得
		if (isForUpdate) {
			listPaymentMeans = cmPaymentMeansDao.findForUpdate(kCode);
			listCommutation = cmCommutationDao.findForUpdate(kCode);
			cmResidenceTaxDto = cmResidenceTaxDao.findForUpdate(kCode);
			cmIncomeTaxDto = cmIncomeTaxDao.findForUpdate(kCode);
			listUnitAmount = cmUnitAmountDao.findForUpdate(kCode);
			cmSocInsuranceDto = cmSocInsuranceDao.findForUpdate(kCode);
			cmMidwayEnterDto = cmMidwayEnterDao.findForUpdate(kCode);
		} else {
			listPaymentMeans = cmPaymentMeansDao.findForEmployee(kCode);
			listCommutation = cmCommutationDao.findForEmployee(kCode);
			cmResidenceTaxDto = cmResidenceTaxDao.findForEmployee(kCode);
			listCmResidenceTax = cmResidenceTaxDao.findForEmployeeList(kCode);
			cmIncomeTaxDto = cmIncomeTaxDao.findForEmployee(kCode);
			listCmIncomeTax = cmIncomeTaxDao.findForEmployeeList(kCode);
			listUnitAmount = cmUnitAmountDao.findForEmployee(kCode);
			cmSocInsuranceDto = cmSocInsuranceDao.findForEmployee(kCode);
			listCmSocInsurance = cmSocInsuranceDao.findForEmployeeList(kCode);
			cmMidwayEnterDto = cmMidwayEnterDao.findForKey(kCode);
		}
		// 単価項目リストを取得
		aryUnitType = getPayment(kCode, null, PayrollConst.SLIP_ALL).getUnitItem();
	}
	
	/**
	 * 新規給与伝票インスタンスを取得する。<br>
	 * もとは{@link PayrollAction#getPayment}
	 * @param slipCode 伝票コード
	 * @return 新規給与伝票
	 * @throws NoSuchFieldException 
	 * @throws IllegalAccessException 
	 * @throws SQLException 
	 */
	private Payment getPayment(String kCode, Date calcMonth, String slipCode) throws SQLException,
			IllegalAccessException, NoSuchFieldException {
		PhPaymentDto header = new PhPaymentDto();
		header.setKCode(kCode);
		header.setCalcMonth(calcMonth);
		header.setSlipCode(slipCode);
		return new Payment(header, new PmDetailPtDao(cfg, cmd, aspUser, user, conn).findForSlip(slipCode),
				new PmDetailPaDao(cfg, cmd, aspUser, user, conn).findForSlip(slipCode), new PmDetailPdDao(cfg, cmd,
						aspUser, user, conn).findForSlip(slipCode), new PmDetailPbDao(cfg, cmd, aspUser, user, conn)
					.findForSlip(header.getSlipCode()), new PmDetailPsDao(cfg, cmd, aspUser, user, conn)
					.findForSlip(slipCode), cfg, cmd, aspUser, user, conn);
	}
	
	/**
	 * 会社銀行情報取得
	 * @param confId 設定区分
	 * @return 設定リスト
	 * @throws NoSuchFieldException 
	 * @throws IllegalAccessException 
	 * @throws SQLException 
	 */
	protected String[][] getCoBankArray() throws SQLException, IllegalAccessException, NoSuchFieldException {
		// DAOの宣言
		CmCoBankDao cmCoBankDao = new CmCoBankDao();
		cmCoBankDao.initDao(cfg, cmd, aspUser, user, conn);
		// データの取得
		List<CmCoBankDto> list = cmCoBankDao.findAvailable();
		// データの整形
		String[][] array = new String[list.size()][2];
		for (int i = 0; i < list.size(); i++) {
			CmCoBankDto dto = list.get(i);
			array[i][0] = dto.getCoBankCode();
			array[i][1] = dto.getCoBankCode();
		}
		return array;
	}
	
	/**
	 * 年プルダウン取得
	 * @param year 基準年
	 * @return 年プルダウン用文字列配列
	 */
	protected String[][] getYearArray(int year, int former, int further) {
		String[][] aryYear = new String[former + further + 1][2];
		int i = 0;
		int index = 0;
		for (i = year - former; i < year; i++) {
			aryYear[index][0] = String.valueOf(i);
			aryYear[index][1] = String.valueOf(i);
			index++;
		}
		aryYear[index][0] = String.valueOf(year);
		aryYear[index][1] = String.valueOf(year);
		index++;
		for (i = year + 1; i <= year + further; i++) {
			aryYear[index][0] = String.valueOf(i);
			aryYear[index][1] = String.valueOf(i);
			index++;
		}
		return aryYear;
	}
	
	/**
	 * 銀行データ→JavaScriptファイル変換。<br>
	 * @param path 出力ファイルパス
	 * @param name オブジェクト名
	 * @throws Exception 例外処理が発生した場合
	 */
	public void convFinanceData(String path, boolean isCreate) throws Exception {
		// ファイルを取得
		File file = new File(path);
		// ファイルが存在しない場合またはisCreateがtrueの場合
		if (!file.exists() | isCreate) {
			FileOutputStream fos = new FileOutputStream(path, false);
			OutputStreamWriter osw = new OutputStreamWriter(fos, "Windows-31J");
			StringBuffer sb = new StringBuffer();
			// 銀行名列名設定
			setJSArray(sb);
			osw.write(sb.toString());
			osw.close();
			fos.close();
		}
	}
	
	/**
	 * 銀行名、支店名配列設定
	 * @throws Exception 
	 */
	public void setJSArray(StringBuffer sb) throws Exception {
		// DAOの準備
		CmBankDao dao = new CmBankDao();
		dao.initDao(cfg, cmd, aspUser, user, conn);
		// 情報の取得
		List<CmBankDto> listBank = dao.findAll();
		// 銀行名
		String[] aryJsBankCode = new String[listBank.size()];
		String[] aryJsBankName = new String[listBank.size()];
		for (int i = 0; i < listBank.size(); i++) {
			CmBankDto cmBankDto = listBank.get(i);
			aryJsBankCode[i] = cmBankDto.getBankCode();
			aryJsBankName[i] = cmBankDto.getBankName();
		}
		// DAOの準備
		CmBranchDao cmBranchDao = new CmBranchDao();
		cmBranchDao.initDao(cfg, cmd, aspUser, user, conn);
		// 情報の取得
		List<CmBranchDto> listBranch = cmBranchDao.findAll();
		// 配列の作成
		// 支店名
		String[] aryJsBraBankCode = new String[listBranch.size()];
		String[] aryJsBranchCode = new String[listBranch.size()];
		String[] aryJsBranchName = new String[listBranch.size()];
		for (int i = 0; i < listBranch.size(); i++) {
			aryJsBraBankCode[i] = listBranch.get(i).getBankCode();
			aryJsBranchCode[i] = listBranch.get(i).getBranchCode();
			aryJsBranchName[i] = listBranch.get(i).getBranchName();
		}
		// 銀行名、支店名配列設定
		setJSBankName(sb, aryJsBankCode, aryJsBankName, aryJsBraBankCode, aryJsBranchCode, aryJsBranchName);
	}
	
	/**
	 * JSへ譲渡する銀行名等設定
	 * @param sb
	 */
	private void setJSBankName(StringBuffer sb, String[] aryJsBankCode, String[] aryJsBankName,
			String[] aryJsBraBankCode, String[] aryJsBranchCode, String[] aryJsBranchName) {
		// 銀行コード
		if (aryJsBankCode.length == 0) {
			sb.append("aryJsBankCode = new Array();");
			sb.append(MospConst.LINE_SEPARATOR);
		} else {
			sb.append("aryJsBankCode = new Array(");
			// 設定なし配列をJSへ
			for (int i = 0; i < aryJsBankCode.length; i++) {
				if (i == aryJsBankCode.length - 1) {
					sb.append("\"" + aryJsBankCode[i] + "\"" + ");");
				} else {
					sb.append("\"" + aryJsBankCode[i] + "\"" + ", ");
				}
			}
			sb.append(MospConst.LINE_SEPARATOR);
		}
		// 銀行名
		if (aryJsBankName.length == 0) {
			sb.append("aryJsBankName = new Array();");
			sb.append(MospConst.LINE_SEPARATOR);
		} else {
			sb.append("aryJsBankName = new Array(");
			// 設定なし配列をJSへ
			for (int i = 0; i < aryJsBankName.length; i++) {
				if (i == aryJsBankName.length - 1) {
					sb.append("\"" + aryJsBankName[i] + "\"" + ");");
				} else {
					sb.append("\"" + aryJsBankName[i] + "\"" + ", ");
				}
			}
			sb.append(MospConst.LINE_SEPARATOR);
			
		}
		
		// 支店銀行コード
		if (aryJsBraBankCode.length == 0) {
			sb.append("aryJsBraBankCode = new Array();");
			sb.append(MospConst.LINE_SEPARATOR);
		} else {
			sb.append("aryJsBraBankCode = new Array(");
			// 設定なし配列をJSへ
			for (int i = 0; i < aryJsBraBankCode.length; i++) {
				if (i == aryJsBraBankCode.length - 1) {
					sb.append("\"" + aryJsBraBankCode[i] + "\"" + ");");
				} else {
					sb.append("\"" + aryJsBraBankCode[i] + "\"" + ", ");
				}
			}
			sb.append(MospConst.LINE_SEPARATOR);
		}
		
		// 支店コード
		if (aryJsBranchCode.length == 0) {
			sb.append("aryJsBranchCode = new Array();");
			sb.append(MospConst.LINE_SEPARATOR);
		} else {
			sb.append("aryJsBranchCode = new Array(");
			// 設定なし配列をJSへ
			for (int i = 0; i < aryJsBranchCode.length; i++) {
				if (i == aryJsBranchCode.length - 1) {
					sb.append("\"" + aryJsBranchCode[i] + "\"" + ");");
				} else {
					sb.append("\"" + aryJsBranchCode[i] + "\"" + ", ");
				}
			}
			sb.append(MospConst.LINE_SEPARATOR);
		}
		
		// 支店名
		if (aryJsBranchName.length == 0) {
			sb.append("aryJsBranchName = new Array();");
			sb.append(MospConst.LINE_SEPARATOR);
		} else {
			sb.append("aryJsBranchName = new Array(");
			// 設定なし配列をJSへ
			for (int i = 0; i < aryJsBranchName.length; i++) {
				if (i == aryJsBranchName.length - 1) {
					sb.append("\"" + aryJsBranchName[i] + "\"" + ");");
				} else {
					sb.append("\"" + aryJsBranchName[i] + "\"" + ", ");
				}
			}
		}
		sb.append(MospConst.LINE_SEPARATOR);
	}
	
	/**
	 * 月プルダウンアイテムを取得する。<br>
	 * @return 月プルダウンアイテム
	 */
	protected String[][] getMonthArray() {
		String[][] aryMonth = new String[12][2];
		for (int i = 0; i < 12; i++) {
			aryMonth[i][0] = String.valueOf(i + 1);
			aryMonth[i][1] = String.valueOf(i + 1);
		}
		return aryMonth;
	}
	
	/**
	 * 日プルダウンアイテムを取得する。<br>
	 * @return 日プルダウンアイテム
	 */
	protected String[][] getDayArray() {
		String[][] aryDay = new String[31][2];
		for (int i = 0; i < 31; i++) {
			aryDay[i][0] = String.valueOf(i + 1);
			aryDay[i][1] = String.valueOf(i + 1);
		}
		return aryDay;
	}
	
}
