/*
 * 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.time.bean.impl;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import jp.mosp.framework.base.MospException;
import jp.mosp.framework.base.MospParams;
import jp.mosp.framework.utils.DateUtility;
import jp.mosp.platform.base.PlatformBean;
import jp.mosp.platform.bean.human.HumanReferenceBeanInterface;
import jp.mosp.platform.dao.file.ExportDaoInterface;
import jp.mosp.platform.dao.file.ExportFieldDaoInterface;
import jp.mosp.platform.dao.human.impl.PfmHumanDao;
import jp.mosp.platform.dto.file.ExportDtoInterface;
import jp.mosp.platform.dto.file.ExportFieldDtoInterface;
import jp.mosp.time.bean.ApplicationReferenceBeanInterface;
import jp.mosp.time.bean.CutoffUtilBeanInterface;
import jp.mosp.time.bean.ExportTableReferenceBeanInterface;
import jp.mosp.time.dao.settings.ExportDataDaoInterface;
import jp.mosp.time.dao.settings.TimeSettingDaoInterface;
import jp.mosp.time.dao.settings.impl.TmdAttendanceDao;
import jp.mosp.time.dao.settings.impl.TmdPaidHolidayDao;
import jp.mosp.time.dao.settings.impl.TmdStockHolidayDao;
import jp.mosp.time.dao.settings.impl.TmdTimelyPaidHolidayDao;
import jp.mosp.time.dao.settings.impl.TmdTotalTimeDao;
import jp.mosp.time.dto.settings.ApplicationDtoInterface;
import jp.mosp.time.dto.settings.TimeSettingDtoInterface;

/**
 * エクスポートテーブル参照クラス。
 */
public class ExportTableReferenceBean extends PlatformBean implements ExportTableReferenceBeanInterface {
	
	/**
	 * エクスポートコード。
	 */
	protected String							exportCode;
	
	/**
	 * 開始年。
	 */
	protected int								startYear;
	
	/**
	 * 開始月。
	 */
	protected int								startMonth;
	
	/**
	 * 終了年。
	 */
	protected int								endYear;
	
	/**
	 * 終了月。
	 */
	protected int								endMonth;
	
	/**
	 * 締日コード。
	 */
	protected String							cutoffCode;
	
	/**
	 * 勤務地コード。
	 */
	protected String							workPlaceCode;
	
	/**
	 * 雇用契約コード。
	 */
	protected String							employmentCode;
	
	/**
	 * 所属コード。
	 */
	protected String							sectionCode;
	
	/**
	 * 職位コード。
	 */
	protected String							positionCode;
	
	/**
	 * エクスポートマスタDAO。
	 */
	private ExportDaoInterface					exportDao;
	
	/**
	 * エクスポートフィールドマスタDAO。
	 */
	private ExportFieldDaoInterface				exportFieldDao;
	
	/**
	 * エクスポートデータDAO。
	 */
	private ExportDataDaoInterface				exportDataDao;
	
	/**
	 * 人事マスタ参照。
	 */
	private HumanReferenceBeanInterface			human;
	
	/**
	 * 設定適用管理参照。
	 */
	private ApplicationReferenceBeanInterface	application;
	
	/**
	 * 勤怠設定管理DAO。
	 */
	private TimeSettingDaoInterface				timeSettingDao;
	
	/**
	 * 締日ユーティリティクラス。
	 */
	private CutoffUtilBeanInterface				cutoffUtil;
	

	/**
	 * {@link PlatformBean#PlatformBean()}を実行する。<br>
	 */
	public ExportTableReferenceBean() {
		super();
	}
	
	/**
	 * {@link PlatformBean#PlatformBean(MospParams, Connection)}を実行する。<br>
	 * @param mospParams MosPパラメータクラス
	 * @param connection DBコネクション
	 */
	public ExportTableReferenceBean(MospParams mospParams, Connection connection) {
		super(mospParams, connection);
	}
	
	@Override
	public void initBean() throws MospException {
		exportDao = (ExportDaoInterface)createDao(ExportDaoInterface.class);
		exportFieldDao = (ExportFieldDaoInterface)createDao(ExportFieldDaoInterface.class);
		exportDataDao = (ExportDataDaoInterface)createDao(ExportDataDaoInterface.class);
		human = (HumanReferenceBeanInterface)createBean(HumanReferenceBeanInterface.class);
		application = (ApplicationReferenceBeanInterface)createBean(ApplicationReferenceBeanInterface.class);
		timeSettingDao = (TimeSettingDaoInterface)createDao(TimeSettingDaoInterface.class);
		cutoffUtil = (CutoffUtilBeanInterface)createBean(CutoffUtilBeanInterface.class);
	}
	
	@Override
	public String[][] getSelectTable(String table, String[][] selectSelectedArray) {
		List<String[]> list = new ArrayList<String[]>();
		String[][] columnArray = mospParams.getProperties().getCodeArray(table, false);
		for (String[] aryColumn : columnArray) {
			boolean addFlag = true;
			for (String[] aryField : selectSelectedArray) {
				if (aryColumn[0].equals(aryField[0])) {
					addFlag = false;
					break;
				}
			}
			if (addFlag) {
				list.add(aryColumn);
			}
		}
		return list.toArray(new String[0][0]);
	}
	
	@Override
	public String[][] getSelectSelected(String exportCode) throws MospException {
		String[][] selectSelectedArray = new String[0][0];
		ExportDtoInterface exportDto = exportDao.findForKey(exportCode);
		if (exportDto == null) {
			// 対象データ無し
			return selectSelectedArray;
		}
		List<ExportFieldDtoInterface> exportFieldDtoList = exportFieldDao.findForList(exportCode);
		if (exportFieldDtoList == null || exportFieldDtoList.isEmpty()) {
			// 対象データ無し
			return selectSelectedArray;
		}
		selectSelectedArray = new String[exportFieldDtoList.size()][2];
		int i = 0;
		for (ExportFieldDtoInterface dto : exportFieldDtoList) {
			String fieldName = dto.getFieldName();
			selectSelectedArray[i][0] = fieldName;
			selectSelectedArray[i][1] = mospParams.getProperties().getCodeItemName(exportDto.getExportTable(),
					fieldName);
			i++;
		}
		return selectSelectedArray;
	}
	
	@Override
	public List<String[]> export() throws MospException {
		ExportDtoInterface exportDto = exportDao.findForKey(exportCode);
		if (exportDto == null) {
			return null;
		}
		List<ExportFieldDtoInterface> exportFieldDtoList = exportFieldDao.findForList(exportCode);
		if (exportFieldDtoList.isEmpty()) {
			return null;
		}
		List<String[]> list = new ArrayList<String[]>();
		if (exportDto.getHeader() == 1) {
			// ヘッダが有りの場合
			List<String> headerList = new ArrayList<String>();
			for (ExportFieldDtoInterface exportFieldDto : exportFieldDtoList) {
				headerList.add(mospParams.getProperties().getCodeItemName(exportDto.getExportTable(),
						exportFieldDto.getFieldName()));
			}
			list.add(headerList.toArray(new String[0]));
		}
		// 対象年月及び締日から締期間初日及び最終日を取得
		Date startDate = cutoffUtil.getCutoffFirstDate(cutoffCode, startYear, startMonth);
		Date endDate = cutoffUtil.getCutoffLastDate(cutoffCode, endYear, endMonth);
		ResultSet rs = null;
		boolean isAttendance = TmdAttendanceDao.TABLE.equals(exportDto.getExportTable());
		boolean isTotalTime = TmdTotalTimeDao.TABLE.equals(exportDto.getExportTable());
		boolean isPaidHoliday = TmdPaidHolidayDao.TABLE.equals(exportDto.getExportTable());
		boolean isStockHoliday = TmdStockHolidayDao.TABLE.equals(exportDto.getExportTable());
		boolean isTimelyPaidHoliday = TmdTimelyPaidHolidayDao.TABLE.equals(exportDto.getExportTable());
		if (isAttendance) {
			// 勤怠データ
			rs = exportDataDao.findForAttendance(startDate, endDate, cutoffCode, workPlaceCode, employmentCode,
					sectionCode, positionCode);
		}
		if (isTotalTime) {
			// 勤怠集計データ
			rs = exportDataDao.findForTotalTime(startDate, endDate, cutoffCode, workPlaceCode, employmentCode,
					sectionCode, positionCode);
		}
		if (isPaidHoliday) {
			// 有給休暇データ
			rs = exportDataDao.findForPaidHoliday(startDate, endDate, cutoffCode, workPlaceCode, employmentCode,
					sectionCode, positionCode);
		}
		if (isStockHoliday) {
			// ストック休暇データ
			rs = exportDataDao.findForStockHoliday(startDate, endDate, cutoffCode, workPlaceCode, employmentCode,
					sectionCode, positionCode);
		}
		if (isTimelyPaidHoliday) {
			// 時間単位有給休暇データ
			rs = exportDataDao.findForTimelyPaidHoliday(startDate, endDate, cutoffCode, workPlaceCode, employmentCode,
					sectionCode, positionCode);
		}
		try {
			while (rs != null && rs.next()) {
				List<String> dataList = new ArrayList<String>();
				if (!cutoffCode.isEmpty()) {
					String personalId = "";
					Date targetDate = DateUtility.getFirstDateOfMonth(startYear, startMonth);
					if (isAttendance) {
						// 勤怠データ
						personalId = rs.getString(TmdAttendanceDao.COL_PERSONAL_ID);
						targetDate = rs.getDate(TmdAttendanceDao.COL_WORK_DATE);
					}
					if (isTotalTime) {
						// 勤怠集計データ
						personalId = rs.getString(TmdTotalTimeDao.COL_PERSONAL_ID);
						targetDate = rs.getDate(TmdTotalTimeDao.COL_CALCULATION_DATE);
					}
					if (isPaidHoliday) {
						// 有給休暇データ
						personalId = rs.getString(TmdPaidHolidayDao.COL_PERSONAL_ID);
						targetDate = rs.getDate(TmdPaidHolidayDao.COL_ACTIVATE_DATE);
					}
					if (isStockHoliday) {
						// ストック休暇データ
						personalId = rs.getString(TmdStockHolidayDao.COL_PERSONAL_ID);
						targetDate = rs.getDate(TmdStockHolidayDao.COL_ACTIVATE_DATE);
					}
					if (isTimelyPaidHoliday) {
						// 時間単位有給休暇データ
						personalId = rs.getString(TmdTimelyPaidHolidayDao.COL_PERSONAL_ID);
						targetDate = rs.getDate(TmdTimelyPaidHolidayDao.COL_ACTIVATE_DATE);
					}
					ApplicationDtoInterface applicationDto = application.findForPerson(personalId, targetDate);
					if (applicationDto == null) {
						continue;
					}
					TimeSettingDtoInterface timeSettingDto = timeSettingDao.findForInfo(applicationDto
						.getWorkSettingCode(), targetDate);
					if (timeSettingDto == null) {
						continue;
					}
					if (!cutoffCode.equals(timeSettingDto.getCutoffCode())) {
						continue;
					}
				}
				for (ExportFieldDtoInterface exportFieldDto : exportFieldDtoList) {
					String fieldName = exportFieldDto.getFieldName();
					if (fieldName.equals(PfmHumanDao.COL_EMPLOYEE_CODE)) {
						// 社員コード
						String personalId = "";
						Date targetDate = null;
						if (isAttendance) {
							// 勤怠データ
							personalId = rs.getString(TmdAttendanceDao.COL_PERSONAL_ID);
							targetDate = rs.getDate(TmdAttendanceDao.COL_WORK_DATE);
						}
						if (isTotalTime) {
							// 勤怠集計データ
							personalId = rs.getString(TmdTotalTimeDao.COL_PERSONAL_ID);
							targetDate = rs.getDate(TmdTotalTimeDao.COL_CALCULATION_DATE);
						}
						if (isPaidHoliday) {
							// 有給休暇データ
							personalId = rs.getString(TmdPaidHolidayDao.COL_PERSONAL_ID);
							targetDate = rs.getDate(TmdPaidHolidayDao.COL_ACTIVATE_DATE);
						}
						if (isStockHoliday) {
							// ストック休暇データ
							personalId = rs.getString(TmdStockHolidayDao.COL_PERSONAL_ID);
							targetDate = rs.getDate(TmdStockHolidayDao.COL_ACTIVATE_DATE);
						}
						if (isTimelyPaidHoliday) {
							// 時間単位有給休暇データ
							personalId = rs.getString(TmdTimelyPaidHolidayDao.COL_PERSONAL_ID);
							targetDate = rs.getDate(TmdTimelyPaidHolidayDao.COL_ACTIVATE_DATE);
						}
						dataList.add(human.getEmployeeCode(personalId, targetDate));
						continue;
					}
					if (isAttendance) {
						// 勤怠データ
						if (TmdAttendanceDao.COL_WORK_DATE.equals(fieldName)) {
							// 勤務日
							dataList.add(DateUtility.getStringDate(rs.getDate(fieldName)));
							continue;
						}
						if (TmdAttendanceDao.COL_START_TIME.equals(fieldName)
								|| TmdAttendanceDao.COL_END_TIME.equals(fieldName)) {
							// 始業時刻・終業時刻
							dataList.add(DateUtility.getStringDateAndTime(rs.getTimestamp(fieldName)));
							continue;
						}
					}
					if (isTotalTime && TmdTotalTimeDao.COL_CALCULATION_DATE.equals(fieldName)) {
						// 勤怠集計データ
						// 集計日
						dataList.add(DateUtility.getStringDate(rs.getDate(fieldName)));
						continue;
					}
					if (isPaidHoliday
							&& (TmdPaidHolidayDao.COL_ACTIVATE_DATE.equals(fieldName)
									|| TmdPaidHolidayDao.COL_ACQUISITION_DATE.equals(fieldName) || TmdPaidHolidayDao.COL_LIMIT_DATE
								.equals(fieldName))) {
						// 有給休暇データ
						// 有効日・取得日・期限日
						dataList.add(DateUtility.getStringDate(rs.getDate(fieldName)));
						continue;
					}
					if (isStockHoliday
							&& (TmdStockHolidayDao.COL_ACTIVATE_DATE.equals(fieldName)
									|| TmdStockHolidayDao.COL_ACQUISITION_DATE.equals(fieldName) || TmdStockHolidayDao.COL_LIMIT_DATE
								.equals(fieldName))) {
						// ストック休暇データ
						// 有効日・取得日・期限日
						dataList.add(DateUtility.getStringDate(rs.getDate(fieldName)));
						continue;
					}
					if (isTimelyPaidHoliday
							&& (TmdTimelyPaidHolidayDao.COL_ACTIVATE_DATE.equals(fieldName) || TmdTimelyPaidHolidayDao.COL_ACQUISITION_DATE
								.equals(fieldName))) {
						// 時間単位有給休暇データ
						// 有効日・取得日
						dataList.add(DateUtility.getStringDate(rs.getDate(fieldName)));
						continue;
					}
					dataList.add(rs.getString(fieldName));
				}
				list.add(dataList.toArray(new String[0]));
			}
		} catch (SQLException e) {
			throw new MospException(e);
		}
		exportDataDao.closers();
		return list;
	}
	
	@Override
	public void setExportCode(String exportCode) {
		this.exportCode = exportCode;
	}
	
	@Override
	public void setStartYear(int startYear) {
		this.startYear = startYear;
	}
	
	@Override
	public void setStartMonth(int startMonth) {
		this.startMonth = startMonth;
	}
	
	@Override
	public void setEndYear(int endYear) {
		this.endYear = endYear;
	}
	
	@Override
	public void setEndMonth(int endMonth) {
		this.endMonth = endMonth;
	}
	
	@Override
	public void setCutoffCode(String cutoffCode) {
		this.cutoffCode = cutoffCode;
	}
	
	@Override
	public void setWorkPlaceCode(String workPlaceCode) {
		this.workPlaceCode = workPlaceCode;
	}
	
	@Override
	public void setEmploymentCode(String employmentCode) {
		this.employmentCode = employmentCode;
	}
	
	@Override
	public void setSectionCode(String sectionCode) {
		this.sectionCode = sectionCode;
	}
	
	@Override
	public void setPositionCode(String positionCode) {
		this.positionCode = positionCode;
	}
	
}
