package com.jasamedika.medifirst2000.service.impl;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.apache.commons.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.orm.jpa.JpaSystemException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.jasamedika.medifirst2000.converter.BaseConverterImpl;
import com.jasamedika.medifirst2000.converter.JadwalDokterConverter;
import com.jasamedika.medifirst2000.dao.AntrianPasienDiPeriksaDao;
import com.jasamedika.medifirst2000.dao.JadwalDokterDao;
import com.jasamedika.medifirst2000.dao.PegawaiDao;
import com.jasamedika.medifirst2000.entities.AntrianPasienDiPeriksa;
import com.jasamedika.medifirst2000.entities.JadwalDokter;
import com.jasamedika.medifirst2000.entities.JadwalPraktek;
import com.jasamedika.medifirst2000.entities.Pegawai;
import com.jasamedika.medifirst2000.entities.Ruangan;
import com.jasamedika.medifirst2000.entities.ShiftKerja;
import com.jasamedika.medifirst2000.exception.ServiceVOException;
import com.jasamedika.medifirst2000.service.AbsensiPegawaiService;
import com.jasamedika.medifirst2000.service.JadwalDokterService;
import com.jasamedika.medifirst2000.util.CommonUtil;
import com.jasamedika.medifirst2000.util.JsonUtil;
import com.jasamedika.medifirst2000.vo.AbsensiPegawaiVO;
import com.jasamedika.medifirst2000.vo.JadwalDokter_VO;
import com.jasamedika.medifirst2000.vo.JadwalPraktekVO;
import com.jasamedika.medifirst2000.vo.PegawaiVO;
import com.jasamedika.medifirst2000.vo.RuanganVO;
import com.jasamedika.medifirst2000.vo.UploadExcelVO;

@Service("jadwalDokterService")
public class JadwalDokterServiceImpl extends BaseVoServiceImpl implements JadwalDokterService {

	@Autowired
	private JadwalDokterDao jadwalDokterDao;

	@Autowired
	private JadwalDokterConverter jadwalDokterConverter;

	@Autowired
	private BaseConverterImpl<PegawaiVO, Pegawai> pegawaiConverter;

	@Autowired
	private BaseConverterImpl<RuanganVO, Ruangan> ruanganConverter;

	@Autowired
	private BaseConverterImpl<JadwalPraktekVO, JadwalPraktek> jadwalPraktekConverter;

	@Override
	public JadwalDokter_VO add(JadwalDokter_VO vo) throws JpaSystemException, ServiceVOException {
		return null;
	}

	@Override
	public JadwalDokter_VO update(JadwalDokter_VO vo) throws JpaSystemException, ServiceVOException {
		return null;
	}

	@Override
	public Boolean delete(Integer key) throws JpaSystemException {
		return null;
	}

	@Override
	public JadwalDokter_VO findById(Integer key) throws JpaSystemException {
		return null;
	}

	@Override
	public List<JadwalDokter_VO> findAll() throws JpaSystemException {
		return null;
	}

	@Override
	public Map<String, Object> findAllWithPageAndLimitAndSortByAndDirectionParameter(Integer page, Integer limit,
			String sort, String dir) {
		return null;
	}

	@Override
	public Map<String, Object> saveJadwalDokter(JadwalDokter_VO vo) {
		Map<String, Object> result = new HashMap<String, Object>();
		JadwalDokter model = jadwalDokterConverter.transferVOToModel(vo, new JadwalDokter());
		JadwalDokter resultModel = jadwalDokterDao.save(model);
		if (CommonUtil.isNotNullOrEmpty(resultModel)) {
			result.put("id", resultModel.getId());
			result.put("Dokter", resultModel.getDokter());
		}
		return result;
	}

	@Override
	public Map<String, Object> updateJadwalDokter(JadwalDokter_VO vo) {
		Map<String, Object> result = new HashMap<String, Object>();
		JadwalDokter model = jadwalDokterDao.findOne(vo.getId());
		model = jadwalDokterConverter.transferVOToModel(vo, model);
		JadwalDokter resultModel = jadwalDokterDao.save(model);
		if (CommonUtil.isNotNullOrEmpty(resultModel)) {
			result.put("id", resultModel.getId());
			result.put("Dokter", resultModel.getDokter());
		}
		return result;
	}

	@Override
	public Map<String, Object> findByRuangan(Integer id) {
		Map<String, Object> result = new HashMap<String, Object>();
		String date = new SimpleDateFormat("yyyy-MM-dd").format(new java.util.Date());
		List<JadwalDokter> resultModel = jadwalDokterDao.findJadwalByRuangan(id, date);
		if (CommonUtil.isNotNullOrEmpty(resultModel)) {

			result.put("data", resultModel);
			result.put("dataFound", true);

		} else {
			result.put("dataFound", false);
		}
		return result;
	}

	@Override
	public Map<String, Object> findByTanggal(Date tanggalJadwal) {
		Map<String, Object> result = new HashMap<String, Object>();
		List<JadwalDokter> resultModel = jadwalDokterDao.findJadwalByTanggal(tanggalJadwal);
		if (CommonUtil.isNotNullOrEmpty(resultModel)) {

			result.put("data", resultModel);
			result.put("dataFound", true);

		} else {
			result.put("dataFound", false);
		}
		return result;
	}

	@Override
	public Map<String, Object> findJadwalByTanggalRuangan(Date tanggalJadwal, Integer idRuangan) {
		Map<String, Object> result = new HashMap<String, Object>();
		List<JadwalDokter> resultModel = jadwalDokterDao.findJadwalByTanggalRuangan(idRuangan, tanggalJadwal);
		if (CommonUtil.isNotNullOrEmpty(resultModel)) {

			try {
				result.put("data", JsonUtil.ToMaps(resultModel));
			} catch (IllegalArgumentException | IllegalAccessException e) {
				e.printStackTrace();
			}
			result.put("dataFound", true);

		} else {
			result.put("dataFound", false);
		}
		return result;
	}

	@Autowired
	private AntrianPasienDiPeriksaDao antrianPasienDiPeriksaDao;

	@Override
	public Map<String, Object> findJadwalByTanggalRuangan(Date tanggalJadwal, String noRec) {
		Map<String, Object> result = new HashMap<String, Object>();

		AntrianPasienDiPeriksa antrian = antrianPasienDiPeriksaDao.findOne(noRec);

		if (CommonUtil.isNotNullOrEmpty(antrian)) {
			List<JadwalDokter> resultModel = jadwalDokterDao.findJadwalByTanggalRuangan(antrian.getRuangan().getId(),
					tanggalJadwal);
			if (CommonUtil.isNotNullOrEmpty(resultModel)) {

				try {
					result.put("data", JsonUtil.ToMaps(resultModel));
				} catch (IllegalArgumentException | IllegalAccessException e) {
					e.printStackTrace();
				}
				result.put("dataFound", true);

			} else {
				result.put("dataFound", false);
			}
		}
		return result;
	}

	@Override
	public Boolean CheckJadwalDokter(Date date, PegawaiVO pegawai) {
		return jadwalDokterDao.CheckJadwalDokter(date, pegawai.getId()) != 0;
	}

	@Override
	public Map<String, Object> getJadwalDokterByIdDokter(Integer idDokter) {
		Map<String, Object> result = new HashMap<String, Object>();
		List<JadwalDokter> resultModel = jadwalDokterDao.getJadwalDokterByIdDokter(idDokter);
		if (CommonUtil.isNotNullOrEmpty(resultModel)) {

			try {
				result.put("data", JsonUtil.ToMaps(resultModel));
			} catch (IllegalArgumentException | IllegalAccessException e) {
				e.printStackTrace();
			}
			result.put("dataFound", true);

		} else {
			result.put("dataFound", false);
		}
		return result;
	}

	/*
	 * create by iwan date : 21.04.2017
	 */
	@Override
	public Map<String, Object> findJadwalDokterByKisaranTglRuangan(int idDokter, int idRuangan, Date from, Date to) {
		Map<String, Object> result = new HashMap<String, Object>();

		List<JadwalDokter> resultModel = jadwalDokterDao.findJadwalDokterByKisaranTglRuangan(idDokter, idRuangan, from,
				to);

		if (CommonUtil.isNotNullOrEmpty(resultModel)) {

			try {
				result.put("data", JsonUtil.ToMaps(resultModel));
			} catch (IllegalArgumentException | IllegalAccessException e) {
				e.printStackTrace();
			}
			result.put("dataFound", true);

		} else {
			result.put("dataFound", false);
		}

		return result;
	}

	/*
	 * create by iwan date : 21.04.2017
	 */
	@Override
	public Map<String, Object> findJadwalDokterByKisaranTglRuanganAll(int idDokter, Date from, Date to) {
		Map<String, Object> result = new HashMap<String, Object>();

		List<JadwalDokter> resultModel = jadwalDokterDao.findJadwalDokterByKisaranTglRuanganAll(idDokter, from, to);

		if (CommonUtil.isNotNullOrEmpty(resultModel)) {

			try {
				result.put("data", JsonUtil.ToMaps(resultModel));
			} catch (IllegalArgumentException | IllegalAccessException e) {
				e.printStackTrace();
			}
			result.put("dataFound", true);

		} else {
			result.put("dataFound", false);
		}

		return result;
	}

	@Override
	public Map<String, Object> getJadwalDokterMingguanByIdDokter(Integer id) {
		Map<String, Object> result = new HashMap<String, Object>();
		Calendar cal = Calendar.getInstance();
		Date now = cal.getTime();

		int next_week = cal.get(Calendar.DATE) + 7;
		cal.set(Calendar.DATE, next_week);
		Date nextWeek = cal.getTime();

		List<JadwalDokter> resultModel = jadwalDokterDao.getJadwalDokterMingguanByIdDokter(id, now, nextWeek);

		if (CommonUtil.isNotNullOrEmpty(resultModel)) {

			try {
				result.put("data", JsonUtil.ToMaps(resultModel));
			} catch (IllegalArgumentException | IllegalAccessException e) {
				e.printStackTrace();
			}
			result.put("dataFound", true);

		} else {
			result.put("dataFound", false);
		}
		return result;
	}

	@Override
	public List<Map<String, Object>> getJadwalSupirAmbulanceByPeriode(Integer bulan, Integer tahun) {

		List<Map<String, Object>> tmpList = new ArrayList<Map<String, Object>>();
		for (Map<String, Object> pegawai : jadwalDokterDao.getSupirAmbulances()) {
			Map<String, Object> data = new HashMap<String, Object>();
			data.put("pegawai", pegawai);
			data.put("listJadwal", jadwalDokterDao
					.getJadwalSupirAmbulanceByIdPegawaiAndPeriode((Integer) pegawai.get("id"), bulan, tahun));
			tmpList.add(data);
		}
		return tmpList;

	}

	@Override
	public List<Map<String, Object>> getJadwalSupirAmbulanByIdAndPeriode(Integer id, Integer bulan, Integer tahun) {

		List<Map<String, Object>> tmpList = new ArrayList<Map<String, Object>>();
		for (Map<String, Object> listJadwalPegawai : jadwalDokterDao.getJadwalSupirAmbulanceByIdPegawaiAndPeriode(id,
				bulan, tahun)) {
			Map<String, Object> data = new HashMap<String, Object>();
			data.put("listJadwal", listJadwalPegawai);
			tmpList.add(data);
		}

		return tmpList;
	}

	@Override
	public Map<String, Object> saveListJadwalDokter(List<JadwalDokter_VO> vos) {
		Map<String, Object> result = new HashMap<String, Object>();
		for (JadwalDokter_VO vo : vos) {
			JadwalDokter model = new JadwalDokter();
			if (vo.getId() != null)
				model.setId(vo.getId());
			if (CommonUtil.isNotNullOrEmpty(vo)) {
				model = jadwalDokterConverter.transferVOToModel(vo, new JadwalDokter());
			}
			if (CommonUtil.isNotNullOrEmpty(vo.getDokter())) {
				model.setDokter(pegawaiConverter.transferVOToModel(vo.getDokter(), new Pegawai()));
			}
			if (CommonUtil.isNotNullOrEmpty(vo.getRuangan())) {
				model.setRuangan(ruanganConverter.transferVOToModel(vo.getRuangan(), new Ruangan()));
			}
			if (CommonUtil.isNotNullOrEmpty(vo.getJadwalPraktek())) {

				model.setJadwalPraktek(
						jadwalPraktekConverter.transferVOToModel(vo.getJadwalPraktek(), new JadwalPraktek()));
			}

			JadwalDokter resultModel = new JadwalDokter();
			if (CommonUtil.isNotNullOrEmpty(model)) {
				resultModel = jadwalDokterDao.save(model);
			}

			if (CommonUtil.isNotNullOrEmpty(resultModel)) {
				result.put("id", resultModel.getId());
				try {
					result.put("Dokter", resultModel.getDokter().ToMap());
				} catch (IllegalArgumentException | IllegalAccessException e) {
					e.printStackTrace();
				}
			}
		}
		return result;
	}

	@Autowired
	private BaseConverterImpl<JadwalDokter_VO, JadwalDokter> jadwalSupirAmbulanceConverter;

	@Override
	public Map<String, Object> saveJadwalSupirAmbulance(JadwalDokter_VO vo) {
		Map<String, Object> result = new HashMap<String, Object>();
		JadwalDokter jadwalSupirAmbulance = new JadwalDokter();
		if (CommonUtil.isNotNullOrEmpty(vo)) {
			jadwalSupirAmbulance = jadwalSupirAmbulanceConverter.transferVOToModel(vo, new JadwalDokter());
		}
		if (CommonUtil.isNotNullOrEmpty(vo.getDokter())) {
			jadwalSupirAmbulance.setDokter(pegawaiConverter.transferVOToModel(vo.getDokter(), new Pegawai()));
		}
		if (CommonUtil.isNotNullOrEmpty(vo.getRuangan())) {
			jadwalSupirAmbulance.setRuangan(ruanganConverter.transferVOToModel(vo.getRuangan(), new Ruangan()));
		}
		if (CommonUtil.isNotNullOrEmpty(vo.getJadwalPraktek())) {
			jadwalSupirAmbulance.setJadwalPraktek(
					jadwalPraktekConverter.transferVOToModel(vo.getJadwalPraktek(), new JadwalPraktek()));
		}

		JadwalDokter model = new JadwalDokter();
		if (CommonUtil.isNotNullOrEmpty(jadwalSupirAmbulance)) {
			model = jadwalDokterDao.save(jadwalSupirAmbulance);
		}

		if (CommonUtil.isNotNullOrEmpty(model)) {
			result.put("data", model.getId());
		}

		return result;
	}

	@Override
	public Map<String, Object> getJadwalSupirByDate(Integer date, Integer month, Integer year) {
		Map<String, Object> result = new HashMap<String, Object>();
		Date fromDate = new Date();
		Date toDate = new Date();

		Calendar calendar = Calendar.getInstance();
		calendar.clear();
		calendar.set(Calendar.YEAR, year);
		calendar.set(Calendar.MONTH, month);
		calendar.set(Calendar.DATE, date);
		fromDate = calendar.getTime();

		calendar = Calendar.getInstance();
		calendar.clear();
		calendar.set(Calendar.YEAR, year);
		calendar.set(Calendar.MONTH, month);
		calendar.set(Calendar.DATE, date + 1);
		toDate = calendar.getTime();

		List<JadwalDokter> list = new ArrayList<JadwalDokter>();
		list = jadwalDokterDao.getJadwalSupirAmbulanceByDate(fromDate, toDate);

		if (CommonUtil.isNotNullOrEmpty(list)) {
			result.put("data", list);
		}

		return result;
	}

	// add by askur 15112016
	@Override
	public Map<String, Object> findJadwalByTanggalRuanganBilik(Date tanggalJadwal, Integer idRuangan) {
		Map<String, Object> result = new HashMap<String, Object>();
		List<JadwalDokter> resultModel = jadwalDokterDao.findJadwalByTanggalRuanganBilik(idRuangan, tanggalJadwal);
		if (CommonUtil.isNotNullOrEmpty(resultModel)) {
			result.put("data", resultModel);
		}
		return result;
	}

	@Autowired
	private AbsensiPegawaiService absensiPegawaiService;

	@Override
	@Transactional(readOnly = false)
	public Map<String, Object> updateListJadwalDokter(List<JadwalDokter_VO> vos) {
		Map<String, Object> result = new HashMap<String, Object>();
		for (JadwalDokter_VO vo : vos) {
			JadwalDokter model = jadwalDokterDao.findOne(vo.getId());
			if (vo.getJadwalPraktek() != null) {
				ShiftKerja statusKehadiran = new ShiftKerja();
				statusKehadiran.setId(vo.getJadwalPraktek().getId());
				model.setStatusKehadiran(statusKehadiran);
			}

			if (CommonUtil.isNotNullOrEmpty(model)) {
				model = jadwalDokterDao.save(model);
			}

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

	@Value("${reportDirectory}")
	String reportDirectory;

	public static void writeByteArraysToFile(String fileName, byte[] content) throws IOException {

		File file = new File(fileName);
		BufferedOutputStream writer = new BufferedOutputStream(new FileOutputStream(file));
		writer.write(content);
		writer.flush();
		writer.close();

	}

	@Override
	public Map<String, Object> uploadAbsensi(UploadExcelVO fileInput) {

		Map<String, Object> result = new HashMap<String, Object>();
		byte[] decodedBytes = Base64.decodeBase64(fileInput.getFileInput());
		String targetFile = reportDirectory + UUID.randomUUID().toString().replaceAll("-", "") + ".txt";
		try {
			try {
				writeByteArraysToFile(targetFile, decodedBytes);
			} catch (IOException e) {
				e.printStackTrace();
			}

			FileInputStream fis;
			try {
				fis = new FileInputStream(targetFile);
				BufferedReader br = new BufferedReader(new InputStreamReader(fis));

				String line = null;
				List<Map<String, Object>> list = new ArrayList<>();
				while ((line = br.readLine()) != null) {
					String[] split = line.split(";");
					Map<String, Object> map = new HashMap<>();
					SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-DD HH:mm");

					map.put("key", split[0] + "-" + split[2].split(" ")[0]);
					map.put("id", split[0]);
					map.put("hari", split[2].split(" ")[0]);
					Integer tahun = Integer.parseInt(split[2].substring(0, 4));
					Integer bulan = Integer.parseInt(split[2].substring(4, 6));
					Integer hari = Integer.parseInt(split[2].substring(6, 8));
					Integer jam = Integer.parseInt(split[2].substring(9, 11));

					Integer detail = Integer.parseInt(split[2].substring(11, 13));

					Date date = new Date(tahun, bulan, Integer.parseInt(split[2].substring(7, 8)),
							Integer.parseInt(split[2].substring(10, 11)), Integer.parseInt(split[2].substring(12, 13)));
					String a = tahun.toString() + "-" + bulan.toString() + "-" + hari.toString() + " " + jam.toString()
							+ ":" + detail.toString();
					date = format.parse(tahun.toString() + "-" + bulan.toString() + "-" + hari.toString() + " "
							+ jam.toString() + ":" + detail.toString());
					date.setMonth(bulan - 1);
					map.put("tgl", date);
					list.add(map);

				}
				br.close();
				result.put("items", list);
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			} catch (ParseException e) {
				e.printStackTrace();
			}

			// Construct BufferedReader from InputStreamReader

		} finally {

		}
		return result;
	}

	@Autowired
	private PegawaiDao pegawaiDao;

	@Override
	public Map<String, Object> saveJadwalPegawai(String idFinger, Date date, Date date2) {
		Pegawai pegawai = pegawaiDao.findByIdFinger(idFinger);
		AbsensiPegawaiVO vo = new AbsensiPegawaiVO();
		vo.setPegawai(pegawaiConverter.transferModelToVO(pegawai, new PegawaiVO()));
		vo.setJamMasuk(date);
		vo.setJamKeluar(date2);
		return absensiPegawaiService.saveAbsensiPegawai(vo);
	}

	@Override
	public Map<String, Object> deleteJadwalDokter(JadwalDokter_VO vo) {
		JadwalDokter pegawai = jadwalDokterDao.findOne(vo.getId());
		jadwalDokterDao.delete(pegawai);
		Map<String, Object> dokter = new HashMap<>();
		dokter.put("data", "SUKSES");
		return dokter;
	}

}
