package com.jasamedika.medifirst2000.service.impl;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.net.MalformedURLException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.joda.time.Chronology;
import org.joda.time.LocalDate;
import org.joda.time.chrono.ISOChronology;
import org.joda.time.chrono.IslamicChronology;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.jasamedika.medifirst2000.constants.Master;
import com.jasamedika.medifirst2000.converter.BaseConverterImpl;
import com.jasamedika.medifirst2000.dao.KalenderDao;
import com.jasamedika.medifirst2000.dao.ListTanggalCutiDao;
import com.jasamedika.medifirst2000.dao.MapKalenderToHariLiburDao;
import com.jasamedika.medifirst2000.dao.MapPegawaiJabatanToUnitKerjaDao;
import com.jasamedika.medifirst2000.dao.MonitoringAbsenDao;
import com.jasamedika.medifirst2000.dao.PegawaiDao;
import com.jasamedika.medifirst2000.dao.PegawaiJadwalKerjaDao;
import com.jasamedika.medifirst2000.dao.ShiftKerjaDao;
import com.jasamedika.medifirst2000.dao.SubUnitKerjaDao;
import com.jasamedika.medifirst2000.dao.UnitKerjaDao;
import com.jasamedika.medifirst2000.dao.custom.PegawaiDaoCustom;
import com.jasamedika.medifirst2000.entities.Kalender;
import com.jasamedika.medifirst2000.entities.Pegawai;
import com.jasamedika.medifirst2000.entities.PegawaiJadwalKerja;
import com.jasamedika.medifirst2000.entities.Ruangan;
import com.jasamedika.medifirst2000.entities.ShiftKerja;
import com.jasamedika.medifirst2000.service.PegawaiJadwalKerjaService;
import com.jasamedika.medifirst2000.service.PegawaiService;
import com.jasamedika.medifirst2000.util.CommonUtil;
import com.jasamedika.medifirst2000.util.DateUtil;
import com.jasamedika.medifirst2000.vo.KalenderVO;
import com.jasamedika.medifirst2000.vo.KelompokShiftVO;
import com.jasamedika.medifirst2000.vo.ListTanggalCutiVO;
import com.jasamedika.medifirst2000.vo.PegawaiJadwalKerjaCustomVO;
import com.jasamedika.medifirst2000.vo.PegawaiJadwalKerjaExcelVO;
import com.jasamedika.medifirst2000.vo.PegawaiJadwalKerjaVO;
import com.jasamedika.medifirst2000.vo.PegawaiVO;
import com.jasamedika.medifirst2000.vo.PlanningPegawaiStatusVO;
import com.jasamedika.medifirst2000.vo.RuanganVO;
import com.jasamedika.medifirst2000.vo.ShiftKerjaVO;

@Service("PegawaiJadwalKerjaService")
public class PegawaiJadwalKerjaServiceImpl extends BaseVoServiceImpl implements PegawaiJadwalKerjaService {

	@Autowired
	private PegawaiJadwalKerjaDao pegawaiJadwalKerjaDao;

	@Autowired
	private BaseConverterImpl<PegawaiVO, Pegawai> pegawaiConverter;

	@Autowired
	private BaseConverterImpl<ShiftKerjaVO, ShiftKerja> shiftKerjaConverter;

	@Autowired
	private BaseConverterImpl<PegawaiJadwalKerjaVO, PegawaiJadwalKerja> pegawaiJadwalKerjaConverter;

	@Autowired
	private BaseConverterImpl<RuanganVO, Ruangan> ruanganConverter;

	@Autowired
	private BaseConverterImpl<KalenderVO, Kalender> kalenderConverter;

	@Autowired
	private MonitoringAbsenDao monitoringAbsenDao;

	@Autowired
	private PegawaiService pegawaiService;

	@Autowired
	private ListTanggalCutiDao listTanggalCutiDao;

	@Autowired
	private MapKalenderToHariLiburDao mapKalenderToHariLiburDao;

	@Autowired
	private PegawaiDao pegawaiDao;

	@Autowired
	private PegawaiDaoCustom pegawaiDaoCustom;

	@Autowired
	private ShiftKerjaDao shiftKerjaDao;

	@Autowired
	private MapPegawaiJabatanToUnitKerjaDao mapPegawaiJabatanToUnitKerjaDao;

	@Autowired
	private KalenderDao kalenderDao;

	@Autowired
	private UnitKerjaDao unitKerjaDao;

	@Autowired
	private SubUnitKerjaDao subunitKerjaDao;

	@Override
	@Transactional(readOnly = true)
	public List<Map<String, Object>> getShiftKerja(int idRuangan) {
		List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
		List<Map<String, Object>> listPegawai = pegawaiJadwalKerjaDao.findPegawaiAktifDanKaryawanByRuangan(idRuangan);
		for (Map<String, Object> pegawai : listPegawai) {
			int idKelompokShift = (Integer) pegawai.get("idShiftKerja");
			List<Map<String, Object>> listShift = new ArrayList<Map<String, Object>>();
			List<Map<String, Object>> listShiftKerja = monitoringAbsenDao.findShiftpegawai(idKelompokShift);
			for (Map<String, Object> shiftKerja : listShiftKerja) {
				Map<String, Object> data = new HashMap<String, Object>();
				data.put("namaShift", shiftKerja.get("namaShift"));
				data.put("idShiftKerja", shiftKerja.get("idShiftKerja"));
				listShift.add(data);
			}
			pegawai.put("listShift", listShift);
			result.add(pegawai);
		}
		return result;
	}

	@Override
	@Transactional(readOnly = false)
	public Map<String, Object> saveJadwalKerja(PegawaiJadwalKerjaCustomVO vo) {
		Map<String, Object> result = new HashMap<String, Object>();
		if (CommonUtil.isNotNullOrEmpty(vo)) {
			for (PegawaiJadwalKerjaVO data : vo.getPegawaiJadwalKerja()) {
				PegawaiJadwalKerja pegawaiJadwalKerja = pegawaiJadwalKerjaConverter.transferVOToModel(data,
						new PegawaiJadwalKerja());
				if (CommonUtil.isNotNullOrEmpty(data.getRuangan())) {
					pegawaiJadwalKerja.setRuangan(ruanganConverter.transferVOToModel(data.getRuangan(), new Ruangan()));
				}
				if (CommonUtil.isNotNullOrEmpty(data.getPegawai())) {
					pegawaiJadwalKerja.setPegawai(pegawaiConverter.transferVOToModel(data.getPegawai(), new Pegawai()));
				}
				if (CommonUtil.isNotNullOrEmpty(data.getShift())) {
					pegawaiJadwalKerja
							.setShift(shiftKerjaConverter.transferVOToModel(data.getShift(), new ShiftKerja()));
				}
				if (CommonUtil.isNotNullOrEmpty(data.getTanggal())) {
					pegawaiJadwalKerja
							.setTanggal(kalenderConverter.transferVOToModel(data.getTanggal(), new Kalender()));
				}
				if (CommonUtil.isNotNullOrEmpty(pegawaiJadwalKerja)) {
					PegawaiJadwalKerja model = pegawaiJadwalKerjaDao.save(pegawaiJadwalKerja);
					result.put(model.getId() + " ", model.getId());
				}
			}
		}
		return result;
	}

	@Override
	@Transactional(readOnly = false)
	public Map<String, Object> saveJadwalPegawai(PegawaiJadwalKerjaVO vo) {
		Map<String, Object> result = new HashMap<String, Object>();
		PegawaiJadwalKerja model = new PegawaiJadwalKerja();
		if (CommonUtil.isNotNullOrEmpty(vo.getId())) {
			model.setId(vo.getId());
		}
		if (CommonUtil.isNotNullOrEmpty(vo)) {
			model = pegawaiJadwalKerjaConverter.transferVOToModel(vo, new PegawaiJadwalKerja());
		}
		if (CommonUtil.isNotNullOrEmpty(vo.getPegawai())) {
			model.setPegawai(pegawaiConverter.transferVOToModel(vo.getPegawai(), new Pegawai()));
		}
		if (CommonUtil.isNotNullOrEmpty(vo.getPegawaiGanti())) {
			model.setPegawaiGanti(pegawaiConverter.transferVOToModel(vo.getPegawaiGanti(), new Pegawai()));
		}
		if (CommonUtil.isNotNullOrEmpty(vo.getRuangan())) {
			model.setRuangan(ruanganConverter.transferVOToModel(vo.getRuangan(), new Ruangan()));
		}
		if (CommonUtil.isNotNullOrEmpty(vo.getShift())) {

			model.setShift(shiftKerjaConverter.transferVOToModel(vo.getShift(), new ShiftKerja()));
		}

		PegawaiJadwalKerja resultModel = new PegawaiJadwalKerja();
		if (CommonUtil.isNotNullOrEmpty(model)) {
			resultModel = pegawaiJadwalKerjaDao.save(model);
		}

		if (CommonUtil.isNotNullOrEmpty(resultModel)) {
			result.put("id", resultModel.getId());
		}
		return result;
	}

	@Override
	@Transactional(readOnly = false)
	public Map<String, Object> saveListJadwalPegawai(List<PegawaiJadwalKerjaVO> vos, boolean isUnggah,
			boolean isPenangguhan) {
		Map<String, Object> result = new HashMap<String, Object>();

		for (PegawaiJadwalKerjaVO vo : vos) {
			boolean editKetidakhadiran = false;
			PegawaiJadwalKerja model = new PegawaiJadwalKerja();
			if (CommonUtil.isNotNullOrEmpty(vo)) {
				model = pegawaiJadwalKerjaConverter.transferVOToModel(vo, new PegawaiJadwalKerja());
				if (CommonUtil.isNotNullOrEmpty(vo.getPegawai())) {
					model.setPegawai(pegawaiConverter.transferVOToModel(vo.getPegawai(), new Pegawai()));
				}
				if (CommonUtil.isNotNullOrEmpty(vo.getPegawaiGanti())) {
					model.setPegawaiGanti(pegawaiConverter.transferVOToModel(vo.getPegawaiGanti(), new Pegawai()));
				}
				if (CommonUtil.isNotNullOrEmpty(vo.getRuangan())) {
					model.setRuangan(ruanganConverter.transferVOToModel(vo.getRuangan(), new Ruangan()));
				}
				if (isPenangguhan && CommonUtil.isNotNullOrEmpty(vo.getShift())
						&& CommonUtil.isNotNullOrEmpty(vo.getShift().getId()) && vo.getShift().getId().equals(0)) {
					if (CommonUtil.isNotNullOrEmpty(vo.getTanggal())) {
						Date tanggal = pegawaiJadwalKerjaDao.getTanggal(vo.getTanggal().getId());
						Map<String, Object> map = pegawaiJadwalKerjaDao.getJadwal(vo.getPegawai().getId(),
								new SimpleDateFormat("yyyy-MM-dd").format(tanggal));
						if (CommonUtil.isNotNullOrEmpty(map) && CommonUtil.isNotNullOrEmpty(map.get("id"))) {
							pegawaiJadwalKerjaDao.delete(Integer.parseInt(map.get("id").toString()));
						}
					}
				} else {
					if (CommonUtil.isNotNullOrEmpty(vo.getShift()) && !vo.getShift().equals(0)) {
						model.setShift(shiftKerjaConverter.transferVOToModel(vo.getShift(), new ShiftKerja()));
						if (CommonUtil.isNotNullOrEmpty(vo.getTanggal())) {
							Date tanggal = pegawaiJadwalKerjaDao.getTanggal(vo.getTanggal().getId());
							Map<String, Object> map = pegawaiJadwalKerjaDao.getJadwal(vo.getPegawai().getId(),
									new SimpleDateFormat("yyyy-MM-dd").format(tanggal));
							model.setTanggal(kalenderConverter.transferVOToModel(vo.getTanggal(), new Kalender()));
							if (CommonUtil.isNotNullOrEmpty(map) && CommonUtil.isNotNullOrEmpty(map.get("id"))) {
								model.setId(Integer.parseInt(map.get("id").toString()));
								if (CommonUtil.isNotNullOrEmpty(map.get("flagKetidakhadiran"))
										&& Boolean.parseBoolean(map.get("flagKetidakhadiran").toString())) {
									editKetidakhadiran = true;
								} else if (isUnggah && vo.getShift().getFlagKetidakhadiran()) {
									editKetidakhadiran = true;
								}
							}
						}

						if (CommonUtil.isNotNullOrEmpty(model) && (isPenangguhan || !editKetidakhadiran)) {
							PegawaiJadwalKerja resultModel = pegawaiJadwalKerjaDao.save(model);
							if (CommonUtil.isNotNullOrEmpty(resultModel)) {
								result.put("id", resultModel.getId());
								try {
									result.put("JadwalKerja", resultModel.ToMap());
								} catch (IllegalArgumentException | IllegalAccessException e) {
									e.printStackTrace();
								}
							}
						}
					}
				}
			}
		}

		return result;
	}

	@Override
	@Transactional
	public Map<String, Object> saveListJadwalPegawaiExcel(List<PegawaiJadwalKerjaExcelVO> vos) {
		List<Integer> listIdPegawai = new ArrayList<>();
		List<String> listKdShift = new ArrayList<>();

		// collect raw data for pegawai
		for (PegawaiJadwalKerjaExcelVO xvo : vos) {
			if (!listKdShift.contains(xvo.getKdShift())) {
				listKdShift.add(xvo.getKdShift().toLowerCase());
			}
			if (CommonUtil.isNotNullOrEmpty(xvo.getPegawai()) && CommonUtil.isNotNullOrEmpty(xvo.getPegawai().getId())
					&& !listIdPegawai.contains(xvo.getPegawai().getId())) {
				listIdPegawai.add(xvo.getPegawai().getId());
			}
		}

		// get additional data and set kelompok shift for pegawai
		List<Map<String, Object>> listShiftKerja = shiftKerjaDao.getListShiftKerja(listKdShift);
		List<Map<String, Object>> listKelompokShiftPegawai = pegawaiDao.getListKelompokShiftKerja(listIdPegawai);
		for (Map<String, Object> ks : listKelompokShiftPegawai) {
			for (PegawaiJadwalKerjaExcelVO vo : vos) {
				if (ks.get("id").equals(vo.getPegawai().getId())) {
					KelompokShiftVO svo = new KelompokShiftVO();
					svo.setId(Integer.parseInt(ks.get("shiftKerjaId").toString()));
					vo.getPegawai().setShiftKerja(svo);
					svo = vo.getPegawai().getShiftKerja();
				}
			}
		}

		// morph kdShift to ShiftKerjaVO
		List<PegawaiJadwalKerjaVO> listPegawaiJadwalKerjaVO = new ArrayList<>();
		for (PegawaiJadwalKerjaExcelVO xvo : vos) {
			PegawaiJadwalKerjaVO vo = new PegawaiJadwalKerjaVO();
			ShiftKerjaVO svo = new ShiftKerjaVO();
			vo.setPegawai(xvo.getPegawai());
			vo.setTanggal(xvo.getTanggal());
			for (Map<String, Object> sk : listShiftKerja) {
				if (sk.get("kodeExternal").toString().toLowerCase().equals(xvo.getKdShift().toLowerCase())
						&& sk.get("kelompokShiftId").equals(xvo.getPegawai().getShiftKerja().getId())) {
					svo.setId(Integer.parseInt(sk.get("id").toString()));
					svo.setFlagKetidakhadiran(Boolean.parseBoolean(sk.get("flagKetidakhadiran").toString()));
					break;
				}
			}
			if (CommonUtil.isNotNullOrEmpty(svo.getId())) {
				vo.setShift(svo);
				listPegawaiJadwalKerjaVO.add(vo);
			}
		}

		return saveListJadwalPegawai(listPegawaiJadwalKerjaVO, true, false);
	}

	@SuppressWarnings("unchecked")
	@Override
	@Transactional
	public List<PegawaiJadwalKerjaVO> generateJadwalKerja(PlanningPegawaiStatusVO vo) {
		List<Map<String, Object>> listTglCuti = new ArrayList<>();
		List<String> listTglCutiDetail = new ArrayList<>();
		List<String> listNorec = new ArrayList<>();
		List<PegawaiJadwalKerjaVO> result = new ArrayList<>();
		DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
		Integer[] intStatusCutiBesarMelahirkan = { 2, 14, 24, 25, 6, 29, 26 };
		Integer idTglCuti1 = null;
		Integer idTglCuti2 = null;

		Integer idStatusPegawai = vo.getStatusPegawaiExec().getId();
		Integer idPegawai = vo.getPegawai().getId();
		Integer idKelShift = listTanggalCutiDao.getKelShift(idPegawai);
		Integer idShiftExec = listTanggalCutiDao.getMappingShiftKerja(idStatusPegawai, idKelShift);
		Integer subUnitKerja = pegawaiService.getRuanganByIdPegawaiCustom(vo.getPegawai().getId());
		Set<ListTanggalCutiVO> listTanggal = vo.getListTanggal();
		for (Iterator<ListTanggalCutiVO> iterator = listTanggal.iterator(); iterator.hasNext();) {
			ListTanggalCutiVO listTanggalCutiVO = iterator.next();
			String noRec = listTanggalCutiVO.getNoRec();
			listNorec.add(noRec);
		}

		// Jika Cuti Besar atau Cuti Melahirkan atau sakit lebih dari 1 hari
		if (listNorec.size() == 2 && Arrays.asList(intStatusCutiBesarMelahirkan).contains(idStatusPegawai)) {
			listTglCutiDetail = listTanggalCutiDao.getListTglCutiByNorecDetail(listNorec);
			if (listTglCutiDetail.size() == 2) {
				idTglCuti1 = listTanggalCutiDao.getIdKalenderByTglCuti(listTglCutiDetail.get(0));
				idTglCuti2 = listTanggalCutiDao.getIdKalenderByTglCuti(listTglCutiDetail.get(1));

				if (idTglCuti1 < idTglCuti2) {
					listTglCuti = listTanggalCutiDao.getListTglCutiByNorec(idTglCuti1, idTglCuti2);
				} else {
					listTglCuti = listTanggalCutiDao.getListTglCutiByNorec(idTglCuti2, idTglCuti1);
				}

			}
		} else {
			listTglCuti = listTanggalCutiDao.getListTglCutiByNorec(listNorec);
		}

		for (Map<String, Object> map : listTglCuti) {
			List<Map<String, Object>> getShiftTglFilled = new ArrayList<>();
			List<Map<String, Object>> getShiftTglEmpty = new ArrayList<>();
			Map<String, Object> generatePegawaiJadwal = pegawaiService.findPegawaiByRuanganRev2(subUnitKerja,
					Integer.parseInt((String) map.get("tahun")), Integer.parseInt((String) map.get("bulan")),
					vo.getPegawai().getId());
			List<Map<String, Object>> getShiftTanggal = (List<Map<String, Object>>) ((Map<String, Object>) ((List<Map<String, Object>>) (List<Map<String, Object>>) generatePegawaiJadwal
					.get("data")).get(0)).get("jadwal");
			// Filtering generate shift tanggal
			for (Map<String, Object> mapShiftTanggal : getShiftTanggal) {
				if ((Integer) ((Map<String, Object>) mapShiftTanggal.get("shift")).get("id") != 0) {
					getShiftTglFilled.add(mapShiftTanggal);
				} else {
					getShiftTglEmpty.add(mapShiftTanggal);
				}
			}
			// Exception for comming schedule
			if (CommonUtil.isNullOrEmpty(getShiftTglEmpty)) {
				getShiftTglEmpty = getShiftTglFilled;
			}
			// Store shift tanggal cuti to PegawaiJadwalKerjaVO
			for (Map<String, Object> mapShiftTanggal : getShiftTglEmpty) {
				// Check and switch shift tanggal cuti when filled or empty
				for (Map<String, Object> mapShiftTglFilled : getShiftTglFilled) {
					if (((Integer) ((Map<String, Object>) mapShiftTanggal.get("tanggal")).get("id"))
							.equals((Integer) ((Map<String, Object>) mapShiftTglFilled.get("tanggal")).get("id"))) {
						mapShiftTanggal = mapShiftTglFilled;
						break;
					}
				}
				// Jika_Cuti_Besar_atau_Cuti_Melahirkan_atau_sakit_lebih_dari_1_hari
				if (listNorec.size() == 2 && Arrays.asList(intStatusCutiBesarMelahirkan).contains(idStatusPegawai)) {
					PegawaiVO pegawai = new PegawaiVO();
					ShiftKerjaVO shiftKerja = new ShiftKerjaVO();
					KalenderVO tanggal = new KalenderVO();
					PegawaiJadwalKerjaVO pov = new PegawaiJadwalKerjaVO();

					Integer idShift = (Integer) ((Map<String, Object>) mapShiftTanggal.get("shift")).get("id");
					Integer idTanggal = (Integer) ((Map<String, Object>) mapShiftTanggal.get("tanggal")).get("id");

					if (idTglCuti1 < idTglCuti2) {
						if (idTglCuti1 <= idTanggal && idTanggal <= idTglCuti2
								&& !Arrays.asList(Master.ShiftKerja.HOLIDAY).contains(idShift)) {
							shiftKerja.setId(idShiftExec);
						} else if (idTglCuti1 <= idTanggal && idTanggal <= idTglCuti2
								&& Arrays.asList(Master.ShiftKerja.HOLIDAY_INCLUDED).contains(idShiftExec)) {
							shiftKerja.setId(idShiftExec);
						} else if (idShift != 0) {
							shiftKerja.setId(idShift);
						}
					} else {
						if (idTglCuti2 <= idTanggal && idTanggal <= idTglCuti1
								&& !Arrays.asList(Master.ShiftKerja.HOLIDAY).contains(idShift)) {
							shiftKerja.setId(idShiftExec);
						} else if (idTglCuti1 <= idTanggal && idTanggal <= idTglCuti2
								&& Arrays.asList(Master.ShiftKerja.HOLIDAY_INCLUDED).contains(idShiftExec)) {
							shiftKerja.setId(idShiftExec);
						} else if (idShift != 0) {
							shiftKerja.setId(idShift);
						}
					}
					pegawai.setId(idPegawai);
					tanggal.setId(idTanggal);

					if (CommonUtil.isNotNullOrEmpty(shiftKerja.getId()) && shiftKerja.getId() != 0
							&& !Arrays.asList(Master.ShiftKerja.HOLIDAY).contains(shiftKerja.getId())) {
						pov.setPegawai(pegawai);
						pov.setShift(shiftKerja);
						pov.setTanggal(tanggal);

						result.add(pov);
					} else if (Arrays.asList(Master.ShiftKerja.HOLIDAY).contains(shiftKerja.getId())
							&& getShiftTglEmpty.size() == getShiftTglFilled.size()) {
						pov.setPegawai(pegawai);
						pov.setShift(shiftKerja);
						pov.setTanggal(tanggal);

						result.add(pov);
					}
				} else {
					PegawaiVO pegawai = new PegawaiVO();
					ShiftKerjaVO shiftKerja = new ShiftKerjaVO();
					KalenderVO tanggal = new KalenderVO();
					PegawaiJadwalKerjaVO pov = new PegawaiJadwalKerjaVO();

					Integer idShift = (Integer) ((Map<String, Object>) mapShiftTanggal.get("shift")).get("id");
					Integer idTanggal = (Integer) ((Map<String, Object>) mapShiftTanggal.get("tanggal")).get("id");
					for (Iterator<ListTanggalCutiVO> iterator = listTanggal.iterator(); iterator.hasNext();) {
						ListTanggalCutiVO listTanggalCutiVO = iterator.next();
						Date tglCuti = listTanggalCutiVO.getTgl();
						String strTglCuti = df.format(tglCuti);
						Integer idTglCuti = listTanggalCutiDao.getIdKalenderByTglCuti(strTglCuti);

						if (idTglCuti.equals(idTanggal)
								&& !Arrays.asList(Master.ShiftKerja.HOLIDAY).contains(idShift)) {
							shiftKerja.setId(idShiftExec);
							break;
						} else if (idTglCuti.equals(idTanggal)
								&& Arrays.asList(Master.ShiftKerja.HOLIDAY_INCLUDED).contains(idShiftExec)) {
							shiftKerja.setId(idShiftExec);
							break;
						} else if (CommonUtil.isNotNullOrEmpty(idShift) && idShift != 0) {
							if (idTglCuti.equals(idTanggal) && !idShiftExec.equals(idShift)) {
								shiftKerja.setId(idShiftExec);
							} else {
								shiftKerja.setId(idShift);
							}
						}

					}
					pegawai.setId(idPegawai);
					tanggal.setId(idTanggal);

					if (CommonUtil.isNotNullOrEmpty(shiftKerja.getId())
							&& !Arrays.asList(Master.ShiftKerja.HOLIDAY).contains(shiftKerja.getId())) {
						pov.setPegawai(pegawai);
						pov.setShift(shiftKerja);
						pov.setTanggal(tanggal);
						result.add(pov);
					} else if (Arrays.asList(Master.ShiftKerja.HOLIDAY).contains(shiftKerja.getId())
							&& getShiftTglEmpty.size() == getShiftTglFilled.size()) {
						pov.setPegawai(pegawai);
						pov.setShift(shiftKerja);
						pov.setTanggal(tanggal);

						result.add(pov);
					}
				}
			}
		}

		return result;
	}

	@SuppressWarnings("unchecked")
	@Override
	@Transactional
	public List<PegawaiJadwalKerjaVO> generateJadwalKerjaPenangguhan(PlanningPegawaiStatusVO vo) {
		List<Map<String, Object>> listTglCuti = new ArrayList<>();
		List<String> listTglCutiDetail = new ArrayList<>();
		List<String> listNorec = new ArrayList<>();
		List<PegawaiJadwalKerjaVO> result = new ArrayList<>();
		DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
		Integer[] intStatusLibur = { 8, 14, 15, 40 };
		Integer[] intStatusSakitAlasanPenting = { 6, 42, 43, 44, 76, 77, 78, 79 };
		/**
		 * adding sakit jika 2 tanggal permohonan
		 */
		Integer[] intStatusCutiBesarMelahirkan = { 2, 14, 24, 25, 6, 29 };
		Integer idTglCuti1 = null;
		Integer idTglCuti2 = null;

		Integer idStatusPegawai = vo.getStatusPegawaiExec().getId();
		Integer idPegawai = vo.getPegawai().getId();
		Integer idKelShift = listTanggalCutiDao.getKelShift(idPegawai);
		Integer idShiftExec = listTanggalCutiDao.getMappingShiftKerja(idStatusPegawai, idKelShift);
		Integer subUnitKerja = pegawaiService.getRuanganByIdPegawaiCustom(vo.getPegawai().getId());
		Set<ListTanggalCutiVO> listTanggal = vo.getListTanggal();
		for (Iterator<ListTanggalCutiVO> iterator = listTanggal.iterator(); iterator.hasNext();) {
			ListTanggalCutiVO listTanggalCutiVO = iterator.next();
			String noRec = listTanggalCutiVO.getNoRec();
			listNorec.add(noRec);
		}

		// Jika Cuti Besar atau Cuti Melahirkan atau sakit lebih dari 1 hari
		if (listNorec.size() == 2 && Arrays.asList(intStatusCutiBesarMelahirkan).contains(idStatusPegawai)) {
			listTglCutiDetail = listTanggalCutiDao.getListTglCutiByNorecDetail(listNorec);
			if (listTglCutiDetail.size() == 2) {
				idTglCuti1 = listTanggalCutiDao.getIdKalenderByTglCuti(listTglCutiDetail.get(0));
				idTglCuti2 = listTanggalCutiDao.getIdKalenderByTglCuti(listTglCutiDetail.get(1));

				if (idTglCuti1 < idTglCuti2) {
					listTglCuti = listTanggalCutiDao.getListTglCutiByNorec(idTglCuti1, idTglCuti2);
				} else {
					listTglCuti = listTanggalCutiDao.getListTglCutiByNorec(idTglCuti2, idTglCuti1);
				}

			}
		} else {
			listTglCuti = listTanggalCutiDao.getListTglCutiByNorec(listNorec);
		}

		for (Map<String, Object> map : listTglCuti) {
			List<Map<String, Object>> getShiftTglFilled = new ArrayList<>();
			List<Map<String, Object>> getShiftTglEmpty = new ArrayList<>();
			Map<String, Object> generatePegawaiJadwal = pegawaiService.findPegawaiByRuanganRev2(subUnitKerja,
					Integer.parseInt((String) map.get("tahun")), Integer.parseInt((String) map.get("bulan")),
					vo.getPegawai().getId());
			List<Map<String, Object>> getShiftTanggal = (List<Map<String, Object>>) ((Map<String, Object>) ((List<Map<String, Object>>) (List<Map<String, Object>>) generatePegawaiJadwal
					.get("data")).get(0)).get("jadwal");
			// Filtering generate shift tanggal
			for (Map<String, Object> mapShiftTanggal : getShiftTanggal) {
				if ((Integer) ((Map<String, Object>) mapShiftTanggal.get("shift")).get("id") != 0) {
					getShiftTglFilled.add(mapShiftTanggal);
				} else {
					getShiftTglEmpty.add(mapShiftTanggal);
				}
			}
			// Exception for comming schedule
			if (CommonUtil.isNullOrEmpty(getShiftTglEmpty)) {
				getShiftTglEmpty = getShiftTglFilled;
			}
			// Store shift tanggal cuti to PegawaiJadwalKerjaVO
			for (Map<String, Object> mapShiftTanggal : getShiftTglEmpty) {
				// Check and switch shift tanggal cuti when filled or empty
				for (Map<String, Object> mapShiftTglFilled : getShiftTglFilled) {
					if (((Integer) ((Map<String, Object>) mapShiftTanggal.get("tanggal")).get("id"))
							.equals((Integer) ((Map<String, Object>) mapShiftTglFilled.get("tanggal")).get("id"))) {
						mapShiftTanggal = mapShiftTglFilled;
						break;
					}
				}
				// Jika Cuti Besar atau Cuti Melahirkan atau sakit lebih dari 1
				// hari
				if (listNorec.size() == 2 && Arrays.asList(intStatusCutiBesarMelahirkan).contains(idStatusPegawai)) {
					PegawaiVO pegawai = new PegawaiVO();
					ShiftKerjaVO shiftKerja = new ShiftKerjaVO();
					KalenderVO tanggal = new KalenderVO();
					PegawaiJadwalKerjaVO pov = new PegawaiJadwalKerjaVO();

					Integer idShift = (Integer) ((Map<String, Object>) mapShiftTanggal.get("shift")).get("id");
					Integer idTanggal = (Integer) ((Map<String, Object>) mapShiftTanggal.get("tanggal")).get("id");

					String namaHari = "";
					if (CommonUtil
							.isNotNullOrEmpty(((Map<String, Object>) mapShiftTanggal.get("tanggal")).get("namaHari"))) {
						namaHari = ((Map<String, Object>) mapShiftTanggal.get("tanggal")).get("namaHari").toString();
					}

					if (CommonUtil.isNotNullOrEmpty(namaHari)) {
						if (idTglCuti1 < idTglCuti2) {
							if (idTglCuti1 <= idTanggal && idTanggal <= idTglCuti2
									&& !Arrays.asList(intStatusLibur).contains(idShift)) {
								if (idKelShift == 1
										&& Arrays.asList(Master.PenangguhanCuti.NONSHIFT_SK).contains(namaHari)) {
									shiftKerja.setId(Master.ShiftKerja.NONSHIFT_SK);
								} else if (idKelShift == 1
										&& Arrays.asList(Master.PenangguhanCuti.NONSHIFT_J).contains(namaHari)) {
									shiftKerja.setId(Master.ShiftKerja.NONSHIFT_J);
								} else if (idKelShift == 2
										&& Arrays.asList(Master.PenangguhanCuti.NONSHIFT_SK).contains(namaHari)) {
									shiftKerja.setId(Master.ShiftKerja.NONSHIFT_PLUS_SK);
								} else if (idKelShift == 2
										&& Arrays.asList(Master.PenangguhanCuti.NONSHIFT_J).contains(namaHari)) {
									shiftKerja.setId(Master.ShiftKerja.NONSHIFT_PLUS_J);
								} else {
									shiftKerja.setId(Master.ShiftKerja.RESET);
								}
							} else if (idTglCuti1 <= idTanggal && idTanggal <= idTglCuti2
									&& Arrays.asList(intStatusSakitAlasanPenting).contains(idShiftExec)) {
								if (idKelShift == 1
										&& Arrays.asList(Master.PenangguhanCuti.NONSHIFT_SK).contains(namaHari)) {
									shiftKerja.setId(Master.ShiftKerja.NONSHIFT_SK);
								} else if (idKelShift == 1
										&& Arrays.asList(Master.PenangguhanCuti.NONSHIFT_J).contains(namaHari)) {
									shiftKerja.setId(Master.ShiftKerja.NONSHIFT_J);
								} else if (idKelShift == 2
										&& Arrays.asList(Master.PenangguhanCuti.NONSHIFT_SK).contains(namaHari)) {
									shiftKerja.setId(Master.ShiftKerja.NONSHIFT_PLUS_SK);
								} else if (idKelShift == 2
										&& Arrays.asList(Master.PenangguhanCuti.NONSHIFT_J).contains(namaHari)) {
									shiftKerja.setId(Master.ShiftKerja.NONSHIFT_PLUS_J);
								} else {
									shiftKerja.setId(Master.ShiftKerja.RESET);
								}
							} else if (idShift != 0) {
								shiftKerja.setId(idShift);
							}
						} else {
							if (idTglCuti2 <= idTanggal && idTanggal <= idTglCuti1
									&& !Arrays.asList(intStatusLibur).contains(idShift)) {
								if (idKelShift == 1
										&& Arrays.asList(Master.PenangguhanCuti.NONSHIFT_SK).contains(namaHari)) {
									shiftKerja.setId(Master.ShiftKerja.NONSHIFT_SK);
								} else if (idKelShift == 1
										&& Arrays.asList(Master.PenangguhanCuti.NONSHIFT_J).contains(namaHari)) {
									shiftKerja.setId(Master.ShiftKerja.NONSHIFT_J);
								} else if (idKelShift == 2
										&& Arrays.asList(Master.PenangguhanCuti.NONSHIFT_SK).contains(namaHari)) {
									shiftKerja.setId(Master.ShiftKerja.NONSHIFT_PLUS_SK);
								} else if (idKelShift == 2
										&& Arrays.asList(Master.PenangguhanCuti.NONSHIFT_J).contains(namaHari)) {
									shiftKerja.setId(Master.ShiftKerja.NONSHIFT_PLUS_J);
								} else {
									shiftKerja.setId(Master.ShiftKerja.RESET);
								}
							} else if (idTglCuti1 <= idTanggal && idTanggal <= idTglCuti2
									&& Arrays.asList(intStatusSakitAlasanPenting).contains(idShiftExec)) {
								if (idKelShift == 1
										&& Arrays.asList(Master.PenangguhanCuti.NONSHIFT_SK).contains(namaHari)) {
									shiftKerja.setId(Master.ShiftKerja.NONSHIFT_SK);
								} else if (idKelShift == 1
										&& Arrays.asList(Master.PenangguhanCuti.NONSHIFT_J).contains(namaHari)) {
									shiftKerja.setId(Master.ShiftKerja.NONSHIFT_J);
								} else if (idKelShift == 2
										&& Arrays.asList(Master.PenangguhanCuti.NONSHIFT_SK).contains(namaHari)) {
									shiftKerja.setId(Master.ShiftKerja.NONSHIFT_PLUS_SK);
								} else if (idKelShift == 2
										&& Arrays.asList(Master.PenangguhanCuti.NONSHIFT_J).contains(namaHari)) {
									shiftKerja.setId(Master.ShiftKerja.NONSHIFT_PLUS_J);
								} else {
									shiftKerja.setId(Master.ShiftKerja.RESET);
								}
							} else if (idShift != 0) {
								shiftKerja.setId(idShift);
							}
						}
					} else {
						shiftKerja.setId(Master.ShiftKerja.RESET);
					}

					pegawai.setId(idPegawai);
					tanggal.setId(idTanggal);

					if (CommonUtil.isNotNullOrEmpty(shiftKerja.getId()) && shiftKerja.getId() != 0
							&& !Arrays.asList(intStatusLibur).contains(shiftKerja.getId())) {
						pov.setPegawai(pegawai);
						pov.setShift(shiftKerja);
						pov.setTanggal(tanggal);
						result.add(pov);
					} else if (Arrays.asList(intStatusLibur).contains(shiftKerja.getId())
							&& getShiftTglEmpty.size() == getShiftTglFilled.size()) {
						pov.setPegawai(pegawai);
						pov.setShift(shiftKerja);
						pov.setTanggal(tanggal);
						result.add(pov);
					}
				} else {
					PegawaiVO pegawai = new PegawaiVO();
					ShiftKerjaVO shiftKerja = new ShiftKerjaVO();
					KalenderVO tanggal = new KalenderVO();
					PegawaiJadwalKerjaVO pov = new PegawaiJadwalKerjaVO();

					Integer idShift = (Integer) ((Map<String, Object>) mapShiftTanggal.get("shift")).get("id");
					Integer idTanggal = (Integer) ((Map<String, Object>) mapShiftTanggal.get("tanggal")).get("id");

					java.time.LocalDate localDate = ((Date) ((Map<String, Object>) mapShiftTanggal.get("tanggal"))
							.get("tanggal")).toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
					if (localDate.isBefore(java.time.LocalDate.now())
							|| (localDate.getMonth().equals(java.time.LocalDate.now().getMonth())
									&& localDate.getYear() == java.time.LocalDate.now().getYear())) {

						Locale id = new Locale("in", "ID");
						String pattern = "EEEE";
						SimpleDateFormat sdf = new SimpleDateFormat(pattern, id);
						String namaHari = sdf
								.format((Date) ((Map<String, Object>) mapShiftTanggal.get("tanggal")).get("tanggal"));

						for (Iterator<ListTanggalCutiVO> iterator = listTanggal.iterator(); iterator.hasNext();) {
							ListTanggalCutiVO listTanggalCutiVO = iterator.next();
							Date tglCuti = listTanggalCutiVO.getTgl();
							String strTglCuti = df.format(tglCuti);
							Integer idTglCuti = listTanggalCutiDao.getIdKalenderByTglCuti(strTglCuti);

							if (idTglCuti.equals(idTanggal) && !Arrays.asList(intStatusLibur).contains(idShift)) {
								if (idKelShift == 1
										&& Arrays.asList(Master.PenangguhanCuti.NONSHIFT_SK).contains(namaHari)) {
									shiftKerja.setId(Master.ShiftKerja.NONSHIFT_SK);
								} else if (idKelShift == 1
										&& Arrays.asList(Master.PenangguhanCuti.NONSHIFT_J).contains(namaHari)) {
									shiftKerja.setId(Master.ShiftKerja.NONSHIFT_J);
								} else if (idKelShift == 2
										&& Arrays.asList(Master.PenangguhanCuti.NONSHIFT_SK).contains(namaHari)) {
									shiftKerja.setId(Master.ShiftKerja.NONSHIFT_PLUS_SK);
								} else if (idKelShift == 2
										&& Arrays.asList(Master.PenangguhanCuti.NONSHIFT_J).contains(namaHari)) {
									shiftKerja.setId(Master.ShiftKerja.NONSHIFT_PLUS_J);
								} else {
									shiftKerja.setId(Master.ShiftKerja.RESET);
								}
								break;
							} else if (idTglCuti.equals(idTanggal)
									&& Arrays.asList(intStatusSakitAlasanPenting).contains(idShiftExec)) {
								if (idKelShift == 1
										&& Arrays.asList(Master.PenangguhanCuti.NONSHIFT_SK).contains(namaHari)) {
									shiftKerja.setId(Master.ShiftKerja.NONSHIFT_SK);
								} else if (idKelShift == 1
										&& Arrays.asList(Master.PenangguhanCuti.NONSHIFT_J).contains(namaHari)) {
									shiftKerja.setId(Master.ShiftKerja.NONSHIFT_J);
								} else if (idKelShift == 2
										&& Arrays.asList(Master.PenangguhanCuti.NONSHIFT_SK).contains(namaHari)) {
									shiftKerja.setId(Master.ShiftKerja.NONSHIFT_PLUS_SK);
								} else if (idKelShift == 2
										&& Arrays.asList(Master.PenangguhanCuti.NONSHIFT_J).contains(namaHari)) {
									shiftKerja.setId(Master.ShiftKerja.NONSHIFT_PLUS_J);
								} else {
									shiftKerja.setId(Master.ShiftKerja.RESET);
								}
								break;
							} else if (CommonUtil.isNotNullOrEmpty(idShift) && idShift != 0) {
								if (idTglCuti.equals(idTanggal) && !idShiftExec.equals(idShift)) {
									if (idKelShift == 1
											&& Arrays.asList(Master.PenangguhanCuti.NONSHIFT_SK).contains(namaHari)) {
										shiftKerja.setId(Master.ShiftKerja.NONSHIFT_SK);
									} else if (idKelShift == 1
											&& Arrays.asList(Master.PenangguhanCuti.NONSHIFT_J).contains(namaHari)) {
										shiftKerja.setId(Master.ShiftKerja.NONSHIFT_J);
									} else if (idKelShift == 2
											&& Arrays.asList(Master.PenangguhanCuti.NONSHIFT_SK).contains(namaHari)) {
										shiftKerja.setId(Master.ShiftKerja.NONSHIFT_PLUS_SK);
									} else if (idKelShift == 2
											&& Arrays.asList(Master.PenangguhanCuti.NONSHIFT_J).contains(namaHari)) {
										shiftKerja.setId(Master.ShiftKerja.NONSHIFT_PLUS_J);
									} else {
										shiftKerja.setId(Master.ShiftKerja.RESET);
									}
								} else {
									shiftKerja.setId(idShift);
								}
							}

						}

						pegawai.setId(idPegawai);
						tanggal.setId(idTanggal);

						if (CommonUtil.isNotNullOrEmpty(shiftKerja.getId())
								&& !Arrays.asList(intStatusLibur).contains(shiftKerja.getId())) {
							pov.setPegawai(pegawai);
							pov.setShift(shiftKerja);
							pov.setTanggal(tanggal);
							result.add(pov);
						} else if (Arrays.asList(intStatusLibur).contains(shiftKerja.getId())
								&& getShiftTglEmpty.size() == getShiftTglFilled.size()) {
							pov.setPegawai(pegawai);
							pov.setShift(shiftKerja);
							pov.setTanggal(tanggal);

							result.add(pov);
						}
					}
				}
			}
		}

		return result;
	}

	@Override
	public Integer findIdKalender(String tanggal) {
		return pegawaiJadwalKerjaDao.getIdTgl(tanggal);
	}

	@Override
	public List<Map<String, Object>> findMappingHariLibur(String tahun) {
		List<Map<String, Object>> result = new ArrayList<>();

		List<Map<String, Object>> data = mapKalenderToHariLiburDao.getMappingHariLibur(tahun);
		for (Map<String, Object> map : data) {
			Map<String, Object> hariLibur = new HashMap<>();
			hariLibur.put("id", map.get("hariLiburId"));
			hariLibur.put("namaHariLibur", map.get("hariLiburName"));
			map.put("hariLibur", hariLibur);

			result.add(map);
		}

		return result;
	}

	@Override
	public Map<String, Object> autoSaveJadwalKerjaNonShift() {

		/*
		 * Perbaikan Method ini mohon untuk diikutsertakan juga memperbaiki
		 * Map<String, Object> findPegawaiByRuanganRev2(Integer ruangan, Integer
		 * tahun, Integer bulan, Integer idPegawai) Map<String, Object>
		 * findPegawaiByRuanganRev2(Integer subUnitKerja, Integer tahun, Integer
		 * bulan)
		 */

		// set auto save untuk bulan ini
		Calendar c = Calendar.getInstance();
		c.setTime(new Date());
		Integer tahun = c.get(Calendar.YEAR);
		Integer bulan = c.get(Calendar.MONTH) + 1;

		// get list pegawai non shift by subunitkerja
		List<Integer> listPegawai = pegawaiDao.getPegawaiNonshift();
		List<PegawaiJadwalKerjaVO> vos = new ArrayList<>();

		if (CommonUtil.isNotNullOrEmpty(listPegawai)) {
			for (Integer idPegawai : listPegawai) {
				// generate jadwal hanya untuk yang belum buat jadwal
				List<PegawaiJadwalKerja> jadwal = pegawaiJadwalKerjaDao.findJadwalByBulan(tahun, bulan, idPegawai);
				if (CommonUtil.isNullOrEmpty(jadwal)) {
					Pegawai pegawai = pegawaiDao.findOne(idPegawai);
					List<Map<String, Object>> mapListHariLibur = pegawaiDaoCustom.findHariLiburPegawaiNonShift(tahun,
							bulan);

					// clear false data
					if (CommonUtil.isNotNullOrEmpty(mapListHariLibur))
						for (Map<String, Object> mh : mapListHariLibur) {
							if (CommonUtil.isNotNullOrEmpty(mh.get("statusEnabled"))
									&& mh.get("statusEnabled").equals(Master.STATUS_ENABLE_FALSE))
								mh.put("namaHariLibur", null);
						}

					// Setting Bulan Ramadhan
					Chronology iso = ISOChronology.getInstance();
					Chronology hijri = IslamicChronology.getInstance();
					Integer bulanHijri;

					List<Map<String, Object>> items = new ArrayList<>();
					try {
						Integer idShift = pegawai.getShiftKerjaId();
						List<Map<String, Object>> listShiftKerja = shiftKerjaDao.findByKelompokShiftId(idShift);
						// Non Shift +
						if (idShift == 2) {
							listShiftKerja.addAll(shiftKerjaDao.findByKelompokShiftId(1));
						}
						List<PegawaiJadwalKerja> resultPegawaiJadwalKerja = pegawaiDaoCustom.findJadwalByTanggal(tahun,
								bulan, idPegawai);

						if (resultPegawaiJadwalKerja.size() == 0) { // Apabila_jadwal_kosong
							if (idShift == 1 || idShift == 2) { // apabila_pegawai_nonshift
								for (Map<String, Object> hariLibur : mapListHariLibur) {
									PegawaiJadwalKerjaVO vo = new PegawaiJadwalKerjaVO();
									ShiftKerjaVO shiftKerjaPegawai = new ShiftKerjaVO();

									if (!CommonUtil.isNotNullOrEmpty(hariLibur.get("namaHariLibur"))) {
										// cek apakah nama harinya adalah jumat,
										// senin-kamis atau sabtu minggu
										if (hariLibur.get("namaHari").toString().equals("Minggu")
												|| hariLibur.get("namaHari").toString().equals("Sabtu")) {
											shiftKerjaPegawai.setId(8);
										} else if (hariLibur.get("namaHari").toString().equals("Jumat")) {
											LocalDate tglIso = new LocalDate(tahun, bulan,
													Integer.parseInt(hariLibur.get("tgl").toString()), iso);
											LocalDate tglHijri = new LocalDate(tglIso.toDateTimeAtStartOfDay(), hijri);
											bulanHijri = tglHijri.getMonthOfYear();
											if (bulanHijri == 9) {
												shiftKerjaPegawai.setId(57); // RMJ
											} else {
												shiftKerjaPegawai.setId(19);
											}
										} else {
											LocalDate tglIso = new LocalDate(tahun, bulan,
													Integer.parseInt(hariLibur.get("tgl").toString()), iso);
											LocalDate tglHijri = new LocalDate(tglIso.toDateTimeAtStartOfDay(), hijri);
											bulanHijri = tglHijri.getMonthOfYear();
											if (bulanHijri == 9) {
												shiftKerjaPegawai.setId(56); // RM
											} else {
												shiftKerjaPegawai.setId(18);
											}
										}
									} else {
										shiftKerjaPegawai.setId(8);
									}
									PegawaiVO peg = new PegawaiVO();
									peg.setId(idPegawai);
									KalenderVO kalendar = new KalenderVO();
									kalendar.setId(Integer.parseInt(hariLibur.get("idKalendar").toString()));
									vo.setPegawai(peg);
									vo.setShift(shiftKerjaPegawai);
									vo.setTanggal(kalendar);
									vos.add(vo);
								}
							} // end if shift 1
							else {// Selain shift 1
								for (Map<String, Object> hariLibur : mapListHariLibur) {
									PegawaiJadwalKerjaVO vo = new PegawaiJadwalKerjaVO();
									PegawaiVO peg = new PegawaiVO();
									peg.setId(idPegawai);
									ShiftKerjaVO shiftKerjaPegawai = new ShiftKerjaVO();
									shiftKerjaPegawai.setId(0);
									KalenderVO kalendar = new KalenderVO();
									kalendar.setId(Integer.parseInt(hariLibur.get("idKalendar").toString()));
									vo.setPegawai(peg);
									vo.setShift(shiftKerjaPegawai);
									vo.setTanggal(kalendar);
									vos.add(vo);
								}
							}
						} else {// Jadwal tidak kosong
							Integer idLooping = 0;
							List<Map<String, Object>> mapListHariLiburTemp = mapListHariLibur;

							for (Map<String, Object> map2 : mapListHariLiburTemp) {

								for (PegawaiJadwalKerja mapPegawaiJadwalKerja : resultPegawaiJadwalKerja) {
									if (mapPegawaiJadwalKerja.getPegawaiId().equals(idPegawai) && (Integer
											.parseInt(map2.get("idKalendar").toString()) == mapPegawaiJadwalKerja
													.getTanggalId())) {
										items.add(mapPegawaiJadwalKerja.ToMap());
										mapListHariLiburTemp.remove(idLooping);

										break;
									}
								}
								idLooping++;
							}
							// Untuk tanggal yang kosong diisi disini
							for (Map<String, Object> map2 : mapListHariLiburTemp) {
								PegawaiJadwalKerjaVO vo = new PegawaiJadwalKerjaVO();
								PegawaiVO peg = new PegawaiVO();
								peg.setId(idPegawai);
								ShiftKerjaVO shiftKerjaPegawai = new ShiftKerjaVO();
								shiftKerjaPegawai.setId(0);
								KalenderVO kalendar = new KalenderVO();
								kalendar.setId(Integer.parseInt(map2.get("idKalendar").toString()));
								vo.setPegawai(peg);
								vo.setShift(shiftKerjaPegawai);
								vo.setTanggal(kalendar);
								vos.add(vo);
							}
						} // end else
					} catch (IllegalArgumentException | IllegalAccessException e) {
						e.printStackTrace();
					}
				} // kondisi tidak ada data di pegawai jadwal kerja
			} // looping pegawai

			if (CommonUtil.isNotNullOrEmpty(vos)) {
				Map<String, Object> result = saveListJadwalPegawai(vos, false, false);
				return result;
			} else {
				return null;
			}

		} else { // kondisi listpegawai not null
			return null;
		}
	}

	@Override
	public void scheduledSaveJadwalKerjaNonShift() {
		autoSaveJadwalKerjaNonShift();
	}

	@Override
	public void deletePegawaiJadwalKerja(Integer id) {
		pegawaiJadwalKerjaDao.delete(id);
	}

	@SuppressWarnings("resource")
	@Override
	public String writeExcelPegawaiJadwalKerja(String bulan, Integer idUnitKerja, Integer idSubunitKerja)
			throws ParseException {
		String absoluteFilePath = "";
		Date start = DateUtil.startMonth(bulan);
		Date end = DateUtil.endMonth(bulan);

		try {
			HSSFWorkbook workbook = new HSSFWorkbook();

			HSSFSheet sheet = workbook.createSheet(new SimpleDateFormat("MMMM yyyy", new Locale("in", "ID"))
					.format(new SimpleDateFormat("yyyy-MM").parse(bulan)));

			Map<String, Object> unitKerja = unitKerjaDao.getUnitKerjaById(idUnitKerja);
			Map<String, Object> subunitKerja = subunitKerjaDao.getSubunitKerjaById(idSubunitKerja);
			List<Map<String, Object>> listTanggal = kalenderDao.getKalenderBulanan(start, end);
			List<Map<String, Object>> listPegawai = mapPegawaiJabatanToUnitKerjaDao.getPegawaiByUnitKerja(idUnitKerja,
					idSubunitKerja);

			List<Object> listIdTanggal = new ArrayList<>();
			List<Object> listKdTanggal = new ArrayList<>();
			listIdTanggal.add("ID");
			listIdTanggal.add("");
			listKdTanggal.add("");
			listKdTanggal.add("NAMA PEGAWAI/ TANGGAL");
			for (Map<String, Object> tanggal : listTanggal) {
				listIdTanggal.add(tanggal.get("id"));
				listKdTanggal.add(tanggal.get("tanggal"));
			}
			Object[] arrId = new Object[listIdTanggal.size()];
			Object[] arrkd = new Object[listKdTanggal.size()];
			listIdTanggal.toArray(arrId);
			listKdTanggal.toArray(arrkd);

			Integer i = 1;
			Map<Integer, Object[]> data = new HashMap<>();
			data.put(i++, arrId);
			data.put(i++, arrkd);
			for (Map<String, Object> pegawai : listPegawai) {
				data.put(i++, new Object[] { pegawai.get("id"), pegawai.get("namaLengkap") });
			}

			TreeMap<Integer, Object[]> sorted = new TreeMap<>();
			sorted.putAll(data);

			Set<Integer> keyset = sorted.keySet();
			int rownum = 0;
			for (Integer key : keyset) {
				Row row = sheet.createRow(rownum++);
				Object[] objArr = data.get(key);
				int cellnum = 0;
				for (Object obj : objArr) {
					Cell cell = row.createCell(cellnum++);
					if (obj instanceof String)
						cell.setCellValue((String) obj);
					else if (obj instanceof Integer)
						cell.setCellValue((Integer) obj);
				}
			}

			sheet.getRow(0).setZeroHeight(true);
			sheet.setColumnHidden(0, true);
			int colnums = sheet.getRow(0).getLastCellNum();
			for (int j = 0; j < colnums; j++) {
				sheet.autoSizeColumn(j);
			}
			sheet.createFreezePane(2, 2);

			String filename = "Jadwal_Dinas_Pegawai_" + unitKerja.get("name").toString().replace(" ", "_") + "_"
					+ subunitKerja.get("name").toString().replace(" ", "_") + ".xls";

			String workingDir = System.getProperty("user.dir");
			String your_os = System.getProperty("os.name").toLowerCase();

			if (your_os.indexOf("win") >= 0) {
				// if_windows
				absoluteFilePath = workingDir + "\\" + filename;
			} else if (your_os.indexOf("nix") >= 0 || your_os.indexOf("nux") >= 0 || your_os.indexOf("mac") >= 0) {
				// if_unix_or_mac
				absoluteFilePath = workingDir + "//tmp//" + filename;
				// absoluteFilePath = workingDir + "/" + filename;
			} else {
				// unknown_os?
				absoluteFilePath = workingDir + "/" + filename;
			}

			FileOutputStream out = new FileOutputStream(new File(absoluteFilePath));
			workbook.write(out);

			out.close();

			return absoluteFilePath;
		} catch (Exception e) {
			e.printStackTrace();

			return absoluteFilePath;
		}
	}

	@Override
	public Resource loadFileAsResource(String fileName) throws Exception {
		try {
			Path filePath = Paths.get(fileName).toAbsolutePath().normalize().resolve(fileName).normalize();
			Resource resource = new UrlResource(filePath.toUri());
			if (resource.exists()) {
				return resource;
			} else {
				throw new FileNotFoundException("File not found " + fileName);
			}
		} catch (MalformedURLException e) {
			throw new FileNotFoundException("File not found " + fileName);
		}
	}

}
