package jp.mosp.payroll.common.action;

import java.io.Serializable;
import java.util.Comparator;
import java.util.List;

import jp.mosp.common.common.MospConst;
import jp.mosp.common.common.MospException;
import jp.mosp.common.common.MospUtility;
import jp.mosp.payroll.base.AdjustmentAction;
import jp.mosp.payroll.base.PayrollConst;
import jp.mosp.payroll.common.vo.AdjustmentListVo;
import jp.mosp.payroll.dao.CdAdjustmentDao;
import jp.mosp.payroll.dto.CdAdjustmentDto;

public class AdjustmentListAction extends AdjustmentAction {

	// コマンド
	private static final String CMD_ADJUSTMENT_LIST_SHOW      = "P3011";
	private static final String CMD_ADJUSTMENT_LIST_SEARCH    = "P3012";
	public  static final String CMD_ADJUSTMENT_LIST_RE_SEARCH = "P3013";
	private static final String CMD_ADJUSTMENT_LIST_SORT      = "P3014";
	
	/**
	 * コンストラクタ
	 */
	public AdjustmentListAction() {
		super();
	}
	
	/**
	 * アクション
	 */
	public void action() throws Exception {
		// DBコネクション取得
		getConnection();
		// PAYROLL権限確認
		confirmPayrollAuth();
		// VOの取得
		AdjustmentListVo vo;
		Object obj = session.getAttribute(MospConst.ATT_FORMER_VO);
		if (obj instanceof AdjustmentListVo) {
			if (cmd.equals(CMD_ADJUSTMENT_LIST_SHOW)) {
				vo = new AdjustmentListVo();
			}else{
				vo = (AdjustmentListVo)obj;
			}
		} else {
			vo = new AdjustmentListVo();
		}
		vo.initVo(cfg, msg, cmd, aspUser, user);
		vo.clearMessage();
		vo.clearErrField();
		storeVo(PayrollConst.VO_ADJUSTMENT_LIST, vo);
		// VO及びフォワード先URLの設定
		setVo(vo);
		setUrl(vo.getRetUrl());
		// コマンド毎の処理
		if (cmd.equals(CMD_ADJUSTMENT_LIST_SHOW)) {
			// 表示
			show(vo);
		} else if (cmd.equals(CMD_ADJUSTMENT_LIST_SEARCH)) {
			// 検索
			vo.setParams(request);
			serachAdjustmentList(vo);
			vo.setFormerKey(vo.KEY_K_CODE);
			vo.setIsAscending(true);
			vo.initListInfo();
		} else if (cmd.equals(CMD_ADJUSTMENT_LIST_RE_SEARCH)) {
			// 再検索
			session.removeAttribute(MospConst.ATT_DTO);
			if (vo.getList() != null && vo.getList().size() > 0) {
				serachAdjustmentList(vo);
				vo.setPageButton();
				sortList(vo);
				show(vo);
			} else {
				show(vo);
			}
		} else if (cmd.equals(CMD_ADJUSTMENT_LIST_SORT)) {
			// ソート
			sortList(key1, vo);
		} else {
			throw new MospException(MospConst.EX_CMD_INVALID);
		}
	}
	
	/**
	 * 表示処理
	 * @param vo ConfirmAttListVoインスタンス
	 * @throws Exception
	 */
	private void show(AdjustmentListVo vo) throws Exception {
		// DBコネクションの取得
		if (conn == null) {
			getConnection();
		}
		// 調整年取得
		int adjustYear = getAdjustYear();
		if (vo.aryPltAdjustYear == null) {
			// 調整年配列取得
			prepareDao();
			List<Integer> listAdjustYear = cdAdjustmentDao.findAdjustYear();
			vo.aryPltAdjustYear = new String[listAdjustYear.size()][2];
			for (int i = 0; i < listAdjustYear.size(); i++) {
				vo.aryPltAdjustYear[i][0] = listAdjustYear.get(i).toString();
				vo.aryPltAdjustYear[i][1] = listAdjustYear.get(i).toString();
			}
			// プルダウン取得
			vo.aryPltAdjustSatus = PayrollConst.getAdjuStatusArray();
		}
		// 初期値設定
		vo.setPltAdjustYear(adjustYear);
		vo.setPltReportYear(adjustYear);
	}
	
	/**
	 * 年末調整データリスト検索
	 * @param vo AdjustmentCalcVoインスタンス
	 * @throws Exception
	 */
	private void serachAdjustmentList(AdjustmentListVo vo) throws Exception {
		// DBコネクションの取得
		getConnection();
		// 検索
		CdAdjustmentDao dao = new CdAdjustmentDao();
		dao.initDao(cfg, cmd, aspUser, user, conn);
		List list = dao.findForCondition(
				vo.getTxtKCode       (),
				vo.getTxtKName       (),
				vo.getTxtKKana       (),
				vo.getPltAdjustYear  (),
				vo.getPltAdjustStatus(),
				vo.getTxtIncTaxFrom  (),
				vo.getTxtIncTaxTo    ()
		);
		// VOに設定
		vo.setFields(list);
		// 対象が無かった場合のメッセージ設定
		if (vo.getEscAryKCode().length == 0) {
			vo.addErrMessage(MospUtility.getMessage(msg, MospConst.MSG_NO_DATA, ""));
		}
	}
	
	/**
	 * ソート
	 * @param key ソートキー
	 * @param vo ソート対象Listを含むVO
	 * @throws MospException
	 */
	private void sortList(String key, AdjustmentListVo vo) throws MospException {
		vo.sortList(key, getComparator(key, vo));
		vo.setFields(vo.getList());
	}
	
	/**
	 * ソート(VO内のキー情報でソート)
	 * @param vo ソート対象Listを含むVO
	 * @throws MospException
	 */
	private void sortList(AdjustmentListVo vo) throws MospException {
		vo.sortList(getComparator(vo.getFormerKey(), vo));
		vo.setFields(vo.getList());
	}
	
	/**
	 * 比較クラス取得
	 * @param key ソートキー
	 * @param vo ソート対象Listを含むVO
	 * @throws MospException
	 */
	private Comparator getComparator(String key, AdjustmentListVo vo) throws MospException {
		Comparator comp = null;
		if (key.equals(vo.KEY_K_CODE)) {
			comp = new CompKCode();
		} else if (key.equals(vo.KEY_ADJUST_YEAR)) {
			comp = new CompAdjustYear();
		} else if (key.equals(vo.KEY_ADJUST_STATUS)) {
			comp = new CompAdjustStatus();
		} else if (key.equals(vo.KEY_TAX_GAP)) {
			comp = new CompTaxGap();
		} else if (key.equals(vo.KEY_FINAL_INCOME_TAX)) {
			comp = new CompFinalIncomeTax();
		} else if (key.equals(vo.KEY_INCOME_DEDUCT_SUM)) {
			comp = new CompDeductionSum();
		} else if (key.equals(vo.KEY_INCOME_TAX_SUM)) {
			comp = new CompIncomeTaxSum();
		} else if (key.equals(vo.KEY_TAXED_PAYMENT_SUM)) {
			comp = new CompTaxedPaymentSum();
		} else {
			throw new MospException(MospConst.EX_SORTKEY_INVALID);
		}
		return comp;
	}
	
	/**
	 * 社員コードによる比較クラス
	 */
	protected static class CompKCode implements Comparator, Serializable {
		private static final long serialVersionUID = 5220555340808662930L;
		public int compare(Object obj1, Object obj2) {
			CdAdjustmentDto dto1 = (CdAdjustmentDto)obj1;
			CdAdjustmentDto dto2 = (CdAdjustmentDto)obj2;
			return dto1.getKCode().compareTo(dto2.getKCode());
		}
	}
	
	/**
	 * 年末調整計算状態による比較クラス
	 */
	protected static class CompAdjustStatus implements Comparator, Serializable {
		private static final long serialVersionUID = -4592881835057165606L;
		public int compare(Object obj1, Object obj2) {
			CdAdjustmentDto dto1 = (CdAdjustmentDto)obj1;
			CdAdjustmentDto dto2 = (CdAdjustmentDto)obj2;
			return dto1.getAdjustStatus().compareTo(dto2.getAdjustStatus());
		}
	}
	
	/**
	 * 調整年による比較クラス
	 */
	protected static class CompAdjustYear implements Comparator, Serializable {
		private static final long serialVersionUID = -3622039419726770777L;
		public int compare(Object obj1, Object obj2) {
			CdAdjustmentDto dto1 = (CdAdjustmentDto)obj1;
			CdAdjustmentDto dto2 = (CdAdjustmentDto)obj2;
			return dto2.getAdjustYear() - dto1.getAdjustYear();
		}
	}
	
	/**
	 * 課税支給合計額による比較クラス
	 */
	protected static class CompTaxedPaymentSum implements Comparator, Serializable {
		private static final long serialVersionUID = 3091328957304744718L;
		public int compare(Object obj1, Object obj2) {
			CdAdjustmentDto dto1 = (CdAdjustmentDto)obj1;
			CdAdjustmentDto dto2 = (CdAdjustmentDto)obj2;
			return dto2.getTaxedPaymentSum() - dto1.getTaxedPaymentSum();
		}
	}
	
	/**
	 * 所得税合計額による比較クラス
	 */
	protected static class CompIncomeTaxSum implements Comparator, Serializable {
		private static final long serialVersionUID = -2896138089581315027L;
		public int compare(Object obj1, Object obj2) {
			CdAdjustmentDto dto1 = (CdAdjustmentDto)obj1;
			CdAdjustmentDto dto2 = (CdAdjustmentDto)obj2;
			return 	dto2.getIncomeTaxSum() - dto1.getIncomeTaxSum();
		}
	}
	
	/**
	 * 所得控除合計額による比較クラス
	 */
	protected static class CompDeductionSum implements Comparator, Serializable {
		private static final long serialVersionUID = 6775416744479857405L;
		public int compare(Object obj1, Object obj2) {
			CdAdjustmentDto dto1 = (CdAdjustmentDto)obj1;
			CdAdjustmentDto dto2 = (CdAdjustmentDto)obj2;
			return 	dto2.getIncomeDeductSum() - dto1.getIncomeDeductSum();
		}
	}
	
	/**
	 * 年税額による比較クラス
	 */
	protected static class CompFinalIncomeTax implements Comparator, Serializable {
		private static final long serialVersionUID = -6913011582384853556L;
		public int compare(Object obj1, Object obj2) {
			CdAdjustmentDto dto1 = (CdAdjustmentDto)obj1;
			CdAdjustmentDto dto2 = (CdAdjustmentDto)obj2;
			return dto2.getFinalIncomeTax() - dto1.getFinalIncomeTax();
		}
	}
	
	/**
	 * 差引徴収税額による比較クラス
	 */
	protected static class CompTaxGap implements Comparator, Serializable {
		private static final long serialVersionUID = -6804699666350327106L;
		public int compare(Object obj1, Object obj2) {
			CdAdjustmentDto dto1 = (CdAdjustmentDto)obj1;
			CdAdjustmentDto dto2 = (CdAdjustmentDto)obj2;
			return dto2.getTaxGap() - dto1.getTaxGap();
		}
	}
	
}
