package jp.mosp.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.action.MosPHumanAction;
import jp.mosp.common.common.MospConst;
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)
		);
	}
	
	/**
	 * 会社銀行情報取得
	 * @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;
	}

}
