/*
 * MosP - Mind Open Source Project    http://www.mosp.jp/
 * Copyright (C) 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 Affero General Public License
 * as published by the Free Software Foundation, either version 3
 * 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 Affero General Public License for more details.
 * 
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package jp.mosp.platform.bean.human.impl;

import java.sql.Connection;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import jp.mosp.framework.base.MospException;
import jp.mosp.framework.base.MospParams;
import jp.mosp.framework.utils.MospUtility;
import jp.mosp.platform.base.PlatformBean;
import jp.mosp.platform.bean.human.HumanSearchBeanInterface;
import jp.mosp.platform.bean.human.RetirementReferenceBeanInterface;
import jp.mosp.platform.bean.human.SuspensionReferenceBeanInterface;
import jp.mosp.platform.bean.human.base.PlatformHumanBean;
import jp.mosp.platform.bean.system.EmploymentContractReferenceBeanInterface;
import jp.mosp.platform.bean.system.PositionReferenceBeanInterface;
import jp.mosp.platform.bean.system.SectionReferenceBeanInterface;
import jp.mosp.platform.bean.system.WorkPlaceReferenceBeanInterface;
import jp.mosp.platform.dao.human.HumanSearchDaoInterface;
import jp.mosp.platform.dto.human.HumanDtoInterface;
import jp.mosp.platform.dto.human.HumanListDtoInterface;
import jp.mosp.platform.dto.human.impl.PfaHumanListDto;

/**
 * 人事マスタ検索クラス。
 */
public class HumanSearchBean extends PlatformHumanBean implements HumanSearchBeanInterface {
	
	/**
	 * フリーワード区切文字。
	 */
	public static final String	FREE_WORD_SEPARATOR	= " ";
	
	/**
	 * 人事情報検索DAO。
	 */
	HumanSearchDaoInterface		dao;
	
	/**
	 * 対象日。
	 */
	protected Date				targetDate;
	
	/**
	 * 社員コード。
	 */
	protected String			employeeCode;
	
	/**
	 * 社員名。
	 */
	protected String			employeeName;
	
	/**
	 * 姓。
	 */
	protected String			lastName;
	
	/**
	 * 名。
	 */
	protected String			firstName;
	
	/**
	 * 姓（カナ）。
	 */
	protected String			lastKana;
	
	/**
	 * 名（カナ）。
	 */
	protected String			firstKana;
	
	/**
	 * 勤務地コード。
	 */
	protected String			workPlaceCode;
	
	/**
	 * 雇用契約コード。
	 */
	protected String			employmentContractCode;
	
	/**
	 * 所属コード。
	 */
	protected String			sectionCode;
	
	/**
	 * 下位所属要否。
	 */
	protected Boolean			needLowerSection;
	
	/**
	 * 職位コード。
	 */
	protected String			positionCode;
	
	/**
	 * 兼務要否。
	 */
	protected Boolean			needConcurrent;
	
	/**
	 * 情報区分。
	 */
	protected String			informationType;
	
	/**
	 * 検索ワード。
	 */
	protected String			searchWord;
	
	/**
	 * 休退職区分。
	 */
	protected String			stateType;
	
	/**
	 * 条件区分（社員コード）。
	 */
	protected String			employeeCodeType;
	
	/**
	 * 条件区分（姓）。
	 */
	protected String			lastNameType;
	
	/**
	 * 条件区分（名）。
	 */
	protected String			firstNameType;
	
	/**
	 * 条件区分（姓（カナ））。
	 */
	protected String			lastKanaType;
	
	/**
	 * 条件区分（名（カナ））。
	 */
	protected String			firstKanaType;
	
	/**
	 * 不要個人ID。
	 */
	protected String			unnecessaryPersonalId;
	
	/**
	 * 承認ロール要否。
	 */
	protected Boolean			needApproverRole;
	
	/**
	 * 操作区分。
	 */
	protected String			operationType;
	
	/**
	 * 期間開始日。
	 */
	protected Date				startDate;
	
	/**
	 * 期間終了日。
	 */
	protected Date				endDate;
	

	/**
	 * {@link PlatformBean#PlatformBean()}を実行する。<br>
	 */
	public HumanSearchBean() {
		super();
	}
	
	/**
	 * {@link PlatformBean#PlatformBean(MospParams, Connection)}を実行する。<br>
	 * @param mospParams MosP処理情報
	 * @param connection DBコネクション
	 */
	public HumanSearchBean(MospParams mospParams, Connection connection) {
		super(mospParams, connection);
	}
	
	@Override
	public void initBean() throws MospException {
		// 人事情報検索DAO取得
		dao = (HumanSearchDaoInterface)createDao(HumanSearchDaoInterface.class);
	}
	
	@Override
	public List<HumanDtoInterface> search() throws MospException {
		// パラメータ準備
		Map<String, Object> param = dao.getParamsMap();
		param.put(HumanSearchDaoInterface.SEARCH_TARGET_DATE, targetDate);
		param.put(HumanSearchDaoInterface.SEARCH_EMPLOYEE_CODE, employeeCode);
		param.put(HumanSearchDaoInterface.SEARCH_EMPLOYEE_CODE_TYPE, employeeCodeType);
		param.put(HumanSearchDaoInterface.SEARCH_EMPLOYEE_NAME, employeeName);
		param.put("lastName", lastName);
		param.put("lastNameType", lastNameType);
		param.put("workPlaceCode", workPlaceCode);
		param.put(HumanSearchDaoInterface.SEARCH_SECTION_CODE, sectionCode);
		param.put(HumanSearchDaoInterface.SEARCH_NEED_LOWER_SECTION, needLowerSection);
		param.put(HumanSearchDaoInterface.SEARCH_POSITION_CODE, positionCode);
		param.put(HumanSearchDaoInterface.SEARCH_NEED_CONCURRENT, needConcurrent);
		param.put("employmentContractCode", employmentContractCode);
		param.put("firstName", firstName);
		param.put("firstNameType", firstNameType);
		param.put("lastKana", lastKana);
		param.put("lastKanaType", lastKanaType);
		param.put("firstKana", firstKana);
		param.put("firstKanaType", firstKanaType);
		param.put(HumanSearchDaoInterface.SEARCH_EMPLOYEE_STATE, stateType);
		param.put(HumanSearchDaoInterface.SEARCH_FREE_WORD_TYPE, informationType);
		// フリーワード配列設定
		String[] aryFreeWord = new String[0];
		if (searchWord != null && searchWord.isEmpty() == false) {
			// 空白で分割
			aryFreeWord = MospUtility.split(searchWord, FREE_WORD_SEPARATOR);
		}
		param.put("freeWord", aryFreeWord);
		// 不要個人IDパラメータ設定
		param.put(HumanSearchDaoInterface.SEARCH_UNNECESSARY_PERSONAL_ID, unnecessaryPersonalId);
		// 承認ロール要否条件パラメータ設定
		param.put(HumanSearchDaoInterface.SEARCH_NEED_APPROVER_ROLE, needApproverRole);
		// 範囲条件パラメータ設定
		param.put(HumanSearchDaoInterface.SEARCH_RANGE_WORK_PLACE, getRangeWorkPlace(operationType));
		param.put(HumanSearchDaoInterface.SEARCH_RANGE_EMPLOYMENT_CONTRACT, getRangeEmploymentContract(operationType));
		param.put(HumanSearchDaoInterface.SEARCH_RANGE_SECTION, getRangeSection(operationType));
		param.put(HumanSearchDaoInterface.SEARCH_RANGE_POSITION, getRangePosition(operationType));
		param.put(HumanSearchDaoInterface.SEARCH_RANGE_EMPLOYEE, getRangeEmployee(operationType));
		// 期間設定
		param.put(HumanSearchDaoInterface.SEARCH_START_DATE, startDate);
		param.put(HumanSearchDaoInterface.SEARCH_END_DATE, endDate);
		// 検索
		return dao.findForSearch(param);
	}
	
	@Override
	public List<HumanListDtoInterface> getHumanList() throws MospException {
		// 人事マスタ検索
		List<HumanDtoInterface> list = search();
		// 対象日における各種マスタの情報を取得
		WorkPlaceReferenceBeanInterface workPlace;
		SectionReferenceBeanInterface section;
		PositionReferenceBeanInterface position;
		EmploymentContractReferenceBeanInterface empContract;
		RetirementReferenceBeanInterface retire;
		SuspensionReferenceBeanInterface suspension;
		workPlace = (WorkPlaceReferenceBeanInterface)createBean(WorkPlaceReferenceBeanInterface.class);
		section = (SectionReferenceBeanInterface)createBean(SectionReferenceBeanInterface.class);
		position = (PositionReferenceBeanInterface)createBean(PositionReferenceBeanInterface.class);
		empContract = (EmploymentContractReferenceBeanInterface)createBean(EmploymentContractReferenceBeanInterface.class);
		retire = (RetirementReferenceBeanInterface)createBean(RetirementReferenceBeanInterface.class);
		suspension = (SuspensionReferenceBeanInterface)createBean(SuspensionReferenceBeanInterface.class);
		String[][] aryWorkPlace = workPlace.getSelectArray(targetDate, true, null);
		String[][] aryEmploymentContract = empContract.getSelectArray(targetDate, true, null);
		String[][] arySection = section.getNameSelectArray(targetDate, true, null);
		String[][] aryPosition = position.getSelectArray(targetDate, true, null);
		// 人事情報リスト準備
		List<HumanListDtoInterface> humanList = new ArrayList<HumanListDtoInterface>();
		// 検索結果から人事情報リストを作成
		for (HumanDtoInterface dto : list) {
			// 初期化
			HumanListDtoInterface humanListDto = new PfaHumanListDto();
			// 人事基本情報設定
			humanListDto.setPfmHumanId(String.valueOf(dto.getPfmHumanId()));
			humanListDto.setEmployeeCode(dto.getEmployeeCode());
			humanListDto.setLastName(dto.getLastName());
			humanListDto.setFirstName(dto.getFirstName());
			humanListDto.setLastKana(dto.getLastKana());
			humanListDto.setFirstKana(dto.getFirstKana());
			// 勤務地情報設定
			humanListDto.setWorkPlaceCode(dto.getWorkPlaceCode());
			if (dto.getWorkPlaceCode().isEmpty() == false) {
				humanListDto.setWorkPlaceAbbr(getCodeName(dto.getWorkPlaceCode(), aryWorkPlace));
			}
			// 所属情報設定
			humanListDto.setSectionCode(dto.getSectionCode());
			if (dto.getSectionCode().isEmpty() == false) {
				humanListDto.setSectionName(getCodeName(dto.getSectionCode(), arySection));
			}
			// 職位情報設定
			humanListDto.setPositionCode(dto.getPositionCode());
			if (dto.getPositionCode().isEmpty() == false) {
				humanListDto.setPositionAbbr(getCodeName(dto.getPositionCode(), aryPosition));
			}
			// 雇用契約情報設定
			humanListDto.setEmploymentContractCode(dto.getEmploymentContractCode());
			if (dto.getEmploymentContractCode().isEmpty() == false) {
				humanListDto.setEmploymentContractAbbr(getCodeName(dto.getEmploymentContractCode(),
						aryEmploymentContract));
			}
			// 休退職情報設定
			if (retire.isRetired(dto.getPersonalId(), targetDate)) {
				humanListDto.setRetireState(mospParams.getProperties().getName("RetirementOn"));
			} else if (suspension.isSuspended(dto.getPersonalId(), targetDate)) {
				humanListDto.setRetireState(mospParams.getProperties().getName("RetirementLeave"));
			} else {
				humanListDto.setRetireState(mospParams.getProperties().getName("RetirementOff"));
			}
			// 人事情報リストに追加
			humanList.add(humanListDto);
		}
		return humanList;
	}
	
	@Override
	public Set<String> getPersonalIdSet() throws MospException {
		// 人事マスタ検索
		List<HumanDtoInterface> list = search();
		// 個人IDセット準備
		Set<String> set = new HashSet<String>();
		// 人事情報毎に処理
		for (HumanDtoInterface dto : list) {
			set.add(dto.getPersonalId());
		}
		return set;
	}
	
	@Override
	public String[][] getCodedSelectArray(boolean needBlank) throws MospException {
		// プルダウン用配列取得(コード)
		return getSelectArray(needBlank, true);
	}
	
	/**
	 * プルダウン用配列を取得する。<br>
	 * @param needBlank 空白行要否(true：空白行要、false：空白行不要)
	 * @param viewCode  コード表示(true：コード表示、false：コード非表示)
	 * @return プルダウン用配列
	 * @throws MospException インスタンスの取得或いはSQL実行に失敗した場合
	 */
	protected String[][] getSelectArray(boolean needBlank, boolean viewCode) throws MospException {
		// 人事マスタ検索
		List<HumanDtoInterface> list = search();
		// 一覧件数確認
		if (list.size() == 0) {
			// 対象データ無し
			return getNoObjectDataPulldown();
		}
		// コード最大長取得
		int length = getMaxCodeLength(list, viewCode);
		// プルダウン用配列及びインデックス準備
		String[][] array = prepareSelectArray(list.size(), needBlank);
		int idx = needBlank ? 1 : 0;
		// プルダウン用配列作成
		for (HumanDtoInterface dto : list) {
			// コード設定
			array[idx][0] = dto.getPersonalId();
			// 表示内容設定
			if (viewCode) {
				// コード表示
				array[idx++][1] = getCodedName(dto.getEmployeeCode(), getHumanName(dto), length);
			} else {
				// コード非表示
				array[idx++][1] = getHumanName(dto);
			}
		}
		return array;
	}
	
	/**
	 * リスト中のDTOにおけるコード最大文字数を取得する。<br>
	 * @param list     対象リスト
	 * @param viewCode コード表示(true：コード表示、false：コード非表示)
	 * @return リスト中のDTOにおけるコード最大文字数
	 */
	protected int getMaxCodeLength(List<HumanDtoInterface> list, boolean viewCode) {
		// コード表示確認
		if (viewCode == false) {
			return 0;
		}
		// コード最大文字数
		int length = 0;
		// コード最大文字数確認
		for (HumanDtoInterface dto : list) {
			if (dto.getEmployeeCode().length() > length) {
				length = dto.getEmployeeCode().length();
			}
		}
		return length;
	}
	
	@Override
	public void setTargetDate(Date targetDate) {
		this.targetDate = getDateClone(targetDate);
	}
	
	@Override
	public void setEmployeeCode(String employeeCode) {
		this.employeeCode = employeeCode;
	}
	
	@Override
	public void setEmployeeName(String employeeName) {
		this.employeeName = employeeName;
	}
	
	@Override
	public void setLastName(String lastName) {
		this.lastName = lastName;
	}
	
	@Override
	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}
	
	@Override
	public void setLastKana(String lastKana) {
		this.lastKana = lastKana;
	}
	
	@Override
	public void setFirstKana(String firstKana) {
		this.firstKana = firstKana;
	}
	
	@Override
	public void setSectionCode(String sectionCode) {
		this.sectionCode = sectionCode;
	}
	
	@Override
	public void setNeedLowerSection(boolean needLowerSection) {
		this.needLowerSection = Boolean.valueOf(needLowerSection);
	}
	
	@Override
	public void setPositionCode(String positionCode) {
		this.positionCode = positionCode;
	}
	
	@Override
	public void setNeedConcurrent(boolean needConcurrent) {
		this.needConcurrent = Boolean.valueOf(needConcurrent);
	}
	
	@Override
	public void setEmploymentContractCode(String employmentContractCode) {
		this.employmentContractCode = employmentContractCode;
	}
	
	@Override
	public void setWorkPlaceCode(String workPlaceCode) {
		this.workPlaceCode = workPlaceCode;
	}
	
	@Override
	public void setInformationType(String informationType) {
		this.informationType = informationType;
	}
	
	@Override
	public void setSearchWord(String searchWord) {
		this.searchWord = searchWord;
	}
	
	@Override
	public void setStateType(String stateType) {
		this.stateType = stateType;
	}
	
	@Override
	public void setEmployeeCodeType(String employeeCodeType) {
		this.employeeCodeType = employeeCodeType;
	}
	
	@Override
	public void setLastNameType(String lastNameType) {
		this.lastNameType = lastNameType;
	}
	
	@Override
	public void setFirstNameType(String firstNameType) {
		this.firstNameType = firstNameType;
	}
	
	@Override
	public void setLastKanaType(String lastKanaType) {
		this.lastKanaType = lastKanaType;
	}
	
	@Override
	public void setFirstKanaType(String firstKanaType) {
		this.firstKanaType = firstKanaType;
	}
	
	@Override
	public void setUnnecessaryPersonalId(String unnecessaryPersonalId) {
		this.unnecessaryPersonalId = unnecessaryPersonalId;
	}
	
	@Override
	public void setNeedApproverRole(boolean needApproverRole) {
		this.needApproverRole = Boolean.valueOf(needApproverRole);
	}
	
	@Override
	public void setOperationType(String operationType) {
		this.operationType = operationType;
	}
	
	@Override
	public void setStartDate(Date startDate) {
		this.startDate = getDateClone(startDate);
	}
	
	@Override
	public void setEndDate(Date endDate) {
		this.endDate = getDateClone(endDate);
	}
	
}
