/********************************************************************************
 * Copyright (c) 2018 Mettenmeier GmbH 
 *
 * See the NOTICE file(s) distributed with this work for additional 
 * information regarding copyright ownership.
 *
 * This program and the accompanying materials are made available under the 
 * terms of the Eclipse Public License 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0
 *
 * SPDX-License-Identifier: EPL-2.0 
 ********************************************************************************/
package org.eclipse.openk.sp.controller.planning;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.collections.CollectionUtils;
import org.apache.log4j.Logger;
import org.eclipse.openk.sp.controller.AbstractController;
import org.eclipse.openk.sp.controller.validation.ValidationController;
import org.eclipse.openk.sp.db.dao.CalendarRepository;
import org.eclipse.openk.sp.db.dao.StandbyDurationRepository;
import org.eclipse.openk.sp.db.dao.StandbyGroupRepository;
import org.eclipse.openk.sp.db.dao.StandbyListRepository;
import org.eclipse.openk.sp.db.dao.StandbyScheduleBodyRepository;
import org.eclipse.openk.sp.db.dao.StandbyStatusRepository;
import org.eclipse.openk.sp.db.dao.UserInStandbyGroupRepository;
import org.eclipse.openk.sp.db.dao.UserRepository;
import org.eclipse.openk.sp.db.model.CalendarDay;
import org.eclipse.openk.sp.db.model.StandbyDuration;
import org.eclipse.openk.sp.db.model.StandbyGroup;
import org.eclipse.openk.sp.db.model.StandbyScheduleBody;
import org.eclipse.openk.sp.db.model.User;
import org.eclipse.openk.sp.db.model.UserInStandbyGroup;
import org.eclipse.openk.sp.dto.StandbyScheduleBlueprintDto;
import org.eclipse.openk.sp.dto.planning.PlanningBodyResultDto;
import org.eclipse.openk.sp.dto.planning.PlanningMsgDto;
import org.eclipse.openk.sp.dto.planning.PlanningMsgResponseDto;
import org.eclipse.openk.sp.dto.planning.PlanningPhaseDto;
import org.eclipse.openk.sp.dto.planning.StandbyScheduleActionDto;
import org.eclipse.openk.sp.exceptions.SpErrorEntry;
import org.eclipse.openk.sp.exceptions.SpException;
import org.eclipse.openk.sp.exceptions.SpExceptionEnum;
import org.eclipse.openk.sp.mail.MailRequest;
import org.eclipse.openk.sp.util.DateHelper;
import org.eclipse.openk.sp.util.SpMsg;
import org.eclipse.openk.sp.util.ValidationHelper;
import org.joda.time.DateTime;
import org.joda.time.Interval;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional(rollbackFor = Exception.class)
/** Class to handle planning operations. */
public class PlanningController extends AbstractController {
	protected static final Logger LOGGER = Logger.getLogger(PlanningController.class);
	public static final String TXT_AUTOMATIC_PLANNING = "autom. Planung";
	public static final String TXT_AUTOMATIC_PLANNING_HOLIDAY = "autom. Planung (Dienstfrei)";
	public static final String TXT_AUTOMATIC_CHANGE = "autom. Änderung";
	public static final String TXT_MANUAL_CHANGE = "manuelle Änderung";
	public static final String TXT_AND_MORE = "und weitere";

	@Autowired
	private StandbyGroupRepository standbyGroupRepository;

	@Autowired
	private StandbyListRepository standbyListRepository;

	@Autowired
	private StandbyDurationRepository standbyDurationRepository;

	@Autowired
	private StandbyStatusRepository standbyStatusRepository;

	@Autowired
	private ArchiveController archiveController;

	@Autowired
	private StandbyScheduleBodyRepository standbyScheduleBodyRepository;

	@Autowired
	private UserInStandbyGroupRepository uisgRepository;

	@Autowired
	private UserRepository userRepository;

	@Autowired
	private CalendarRepository calendarRepository;

	@Autowired
	private ValidationController validatonController;

	@Autowired
	private MailRequest mailing;

	private List<PlanningMsgDto> lsPlanningMsg = new ArrayList<>();
	private int warningCounter = 0;

	public PlanningMsgResponseDto startPlanning(StandbyScheduleBlueprintDto standbyBlueprintDto, String username)
			throws SpException {
		PlanningMsgResponseDto responseDto = new PlanningMsgResponseDto();
		try {
			lsPlanningMsg = new ArrayList<>();
			warningCounter = 0;

			// check if input is valid
			if (this.validateInputForPlanCalculation(standbyBlueprintDto)) {
				standbyBlueprintDto.setValidTo(DateHelper.getEndOfDay(standbyBlueprintDto.getValidTo()));

				// calculate the different phases.
				Map<Integer, PlanningPhaseDto> planningPhaseMap = this.calculatePlanningPhaseMap(standbyBlueprintDto);
				this.createMsgNumberOfPhases(planningPhaseMap, standbyBlueprintDto);

				Long lastStartUserId = standbyBlueprintDto.getStartIdOfUser();
				// loop over planning phases

				// delete existing entries
				StandbyGroup stbyGroup = standbyGroupRepository.findOne(standbyBlueprintDto.getStandbyGroupId());
				Date lastCalcDate = DateHelper
						.getEndOfDay(new DateTime(standbyBlueprintDto.getValidTo()).minusSeconds(1).toDate());
				this.changeOrDeleteExistingBodies(stbyGroup,
						new DateTime(DateHelper.getStartOfDay(standbyBlueprintDto.getValidFrom())).plusSeconds(1)
								.toDate(),
						lastCalcDate, 1L, username);

				for (Entry<Integer, PlanningPhaseDto> entry : planningPhaseMap.entrySet()) {
					LOGGER.debug("Start Plannig for phase " + entry.getKey());
					PlanningPhaseDto dto = entry.getValue();
					this.createMsgStartOfPhase(entry.getKey(), dto);
					PlanningBodyResultDto planningBodyResultDto = this.calculatePlanForPhase(dto, lastStartUserId,
							username, entry.getKey(), lastCalcDate);
					lastStartUserId = planningBodyResultDto.getLastUserId();
					this.createMsgEndOfPhase(entry.getKey());
					LOGGER.debug("End Plannig for phase " + entry.getKey());
				}
				standbyScheduleBodyRepository.flush();

				// start validation
				List<String> lsValidationBeanNames = new ArrayList<>();
				lsValidationBeanNames.add(ValidationController.BEAN_GROUP_COVERAGE_VALIDATOR);
				lsValidationBeanNames.add(ValidationController.BEAN_DOUBLE_PLANNED_VALIDATOR);
				lsValidationBeanNames.add(ValidationController.BEAN_PLACEHOLDER_STANDBY_USER_VALIDATOR);

				List<StandbyGroup> lsStandbyGroups = new ArrayList<>();
				lsStandbyGroups.add(standbyGroupRepository.findOne(standbyBlueprintDto.getStandbyGroupId()));

				validatonController.startValidation(standbyBlueprintDto.getValidFrom(),
						standbyBlueprintDto.getValidTo(), lsStandbyGroups, lsValidationBeanNames,
						standbyBlueprintDto.getStatusId(), null);
				responseDto.setLsMsg(lsPlanningMsg);
			}
			return responseDto;
		} catch (SpException e) {
			LOGGER.error(e, e);
			throw e;
		} catch (Exception e) {
			LOGGER.error(e, e);
			SpErrorEntry ee = SpExceptionEnum.DEFAULT_EXCEPTION.getEntry();
			ee.setE(e);
			throw new SpException(ee);
		}
	}

	/**
	 * Method to calculate the different phases for changing groups.
	 * 
	 * @param standbyBlueprintDto
	 * @return
	 * @throws SpException
	 */
	public Map<Integer, PlanningPhaseDto> calculatePlanningPhaseMap(StandbyScheduleBlueprintDto standbyBlueprintDto)
			throws SpException {
		Map<Integer, PlanningPhaseDto> resultMap = new HashMap<>();
		try {
			// start of full planning time slot.
			Date validFrom = standbyBlueprintDto.getValidFrom();

			// end of full planning time slot.
			DateTime dt = new DateTime(standbyBlueprintDto.getValidTo());
			dt = dt.minusSeconds(1);
			Date validTo = dt.toDate();

			// temporal date for calculation
			Date tmpDate = validFrom;
			StandbyGroup group = standbyGroupRepository.findOne(standbyBlueprintDto.getStandbyGroupId());
			StandbyDuration firstDuration = this.getFittingDurationOfGroup(group, validFrom);
			if (firstDuration != null) {
				tmpDate = DateHelper.getDateWithTime(tmpDate, firstDuration.getValidFrom());
				tmpDate = new DateTime(tmpDate).plusSeconds(1).toDate();
			}

			int phase = 1;
			int differenceOfDays = 0;
			while (tmpDate.getTime() < validTo.getTime()) {
				// get fitting duration
				List<StandbyDuration> lsDur = this.getFittingDurationsAroundDate(group, tmpDate);

				StandbyDuration duration = null;
				if (lsDur != null && !lsDur.isEmpty()) {
					duration = lsDur.get(lsDur.size() - 1);

					// current week day
					int tempDateDay = DateHelper.getDayOfWeek(tmpDate);

					// get days between duration start and duration end
					int differenceOfDurationDays = DateHelper.calculateDifferenceOfDays(duration.getValidDayFrom(),
							duration.getValidDayTo(), duration.getValidFrom(), duration.getValidTo());

					// get days between duration start and the current date (tmpDate)
					int differenceOfTempDateAndDurStart = DateHelper.calculateDifferenceOfDays(
							duration.getValidDayFrom(), tempDateDay, duration.getValidFrom(), tmpDate);

					// reduce duration slot with the starting difference
					differenceOfDays = differenceOfDurationDays - differenceOfTempDateAndDurStart;

					Date startOfDuration = DateHelper.getDateWithTime(tmpDate, duration.getValidFrom());
					Date endOfDuration = DateHelper.addDaysToDate(tmpDate, differenceOfDays);
					endOfDuration = DateHelper.getDateWithTime(endOfDuration, duration.getValidTo());

					if (!duration.getNextUserInNextDuration()) {
						// find next duration with a changing user allowed
						StandbyDuration tmpDur = this.getNextDurationWithMaChange(group, endOfDuration);
						if (tmpDur != null) {
							differenceOfDays = DateHelper.calculateDifferenceOfDays(
									DateHelper.getDayOfWeek(startOfDuration), tmpDur.getValidDayTo(), startOfDuration,
									tmpDur.getValidTo());
							endOfDuration = DateHelper.addDaysToDate(tmpDate, differenceOfDays);
							endOfDuration = DateHelper.getDateWithTime(endOfDuration, tmpDur.getValidTo());
						} else {
							LOGGER.debug("Keine Duration für den Tag : " + startOfDuration + " gefunden.");
						}
					}

					if (DateHelper.isDateAfter(endOfDuration, validTo)) {
						endOfDuration = validTo;
					}
					List<UserInStandbyGroup> lsUserInGroup = uisgRepository
							.findUserForInterval(standbyBlueprintDto.getStandbyGroupId(), tmpDate, endOfDuration);
					if (lsUserInGroup != null && !lsUserInGroup.isEmpty()) {
						if (resultMap.containsKey(phase)) {
							PlanningPhaseDto dto = resultMap.get(phase);
							if (CollectionUtils.isEqualCollection(dto.getLsUsers(), lsUserInGroup)) {
								dto.setEndDate(endOfDuration);
							} else {
								phase++;
								LOGGER.debug("Add phase " + phase);
								resultMap.put(phase,
										new PlanningPhaseDto(dto.getEndDate(), endOfDuration, lsUserInGroup));

							}
						} else {
							LOGGER.debug("Add phase " + phase);
							resultMap.put(phase, new PlanningPhaseDto(startOfDuration, endOfDuration, lsUserInGroup));
						}
					} else {
						LOGGER.debug("Keine Gruppe gefunden!");
					}

					if (differenceOfDays == 0) {
						// add at least one day
						differenceOfDays = 1;
					}
					tmpDate = DateHelper.addDaysToDate(tmpDate, differenceOfDays);
				}
			}
			this.logPhases(resultMap);
			return resultMap;
		} catch (Exception e) {
			LOGGER.error(e, e);
			SpErrorEntry ee = SpExceptionEnum.DEFAULT_EXCEPTION.getEntry();
			ee.setE(e);
			throw new SpException(ee);
		}

	}

	/**
	 * Method to search the next standby duration for a group that has the
	 * getNextUserInNextDuration flag = true.
	 * 
	 * @param group
	 * @param date
	 * @return
	 */
	public StandbyDuration getNextDurationWithMaChange(StandbyGroup group, Date date) {
		for (int i = 0; i <= 6; i++) {
			List<StandbyDuration> lsDuration = this.getFittingDurationsByValidTo(group, date);
			for (StandbyDuration stbDur : lsDuration) {
				if (stbDur.getNextUserInNextDuration()) {
					return stbDur;
				}
			}
			date = DateHelper.addDaysToDate(date, 1);
		}
		return null;
	}

	public void changeOrDeleteAtIntervalStart(StandbyScheduleBody body, StandbyDuration duration, Date tmpDate,
			String username) {
		if (duration != null) {
			Date durationStart = DateHelper.getDateWithTime(tmpDate, duration.getValidFrom());
			if (DateHelper.isDateBefore(body.getValidFrom(), durationStart)) {
				if (DateHelper.isDateAfter(body.getValidTo(), durationStart)) {
					body.setValidTo(durationStart);
					body.setModificationDate(new Date());
					body.setModifiedCause(TXT_AUTOMATIC_CHANGE);
					body.setModifiedCause(username);
					standbyScheduleBodyRepository.save(body);
				}
			} else {
				standbyScheduleBodyRepository.delete(body);
			}
		}
	}

	public void changeOrDeleteAtIntervalEnd(StandbyScheduleBody body, StandbyDuration duration, Date tmpDate,
			String username) {
		if (duration != null) {
			Date durationEnd = DateHelper.getDateWithTime(tmpDate, duration.getValidTo());
			if (DateHelper.isDateBefore(body.getValidFrom(), durationEnd)) {
				if (DateHelper.isDateAfter(body.getValidTo(), durationEnd)) {
					body.setValidTo(durationEnd);
					body.setModificationDate(new Date());
					body.setModifiedCause(TXT_AUTOMATIC_CHANGE);
					body.setModifiedCause(username);
					standbyScheduleBodyRepository.save(body);
				}
			} else {
				standbyScheduleBodyRepository.delete(body);
			}
		}
	}

	public void changeOrDeleteExistingBodies(StandbyGroup group, Date startDate, Date endDate, Long statusId,
			String username) {
		startDate = DateHelper.getStartOfDay(startDate);
		Date tmpDate = startDate;
		while (tmpDate.getTime() <= endDate.getTime()) {
			List<StandbyScheduleBody> lsBodies = standbyScheduleBodyRepository
					.findByGroupAndStatusHittingDateInterval(group.getId(), tmpDate, endDate, statusId);

			List<StandbyDuration> lsFittingDurations = this.getFittingDurationsOfGroup(group, tmpDate);
			StandbyDuration duration = null;
			if (lsFittingDurations != null && !lsFittingDurations.isEmpty()) {
				duration = lsFittingDurations.get(0);
			}
			for (StandbyScheduleBody body : lsBodies) {
				// if (tmpDate.getTime() == endDate.getTime()) {
				// this.changeOrDeleteAtIntervalEnd(body, duration, tmpDate, username);
				// } else

				if (body.getValidFrom().getTime() >= startDate.getTime()
						&& body.getValidTo().getTime() <= endDate.getTime()) {
					standbyScheduleBodyRepository.delete(body);
				}

			}
			tmpDate = DateHelper.addDaysToDate(tmpDate, 1);
		}

	}

	public PlanningBodyResultDto calculatePlanForPhase(PlanningPhaseDto dto, Long lastStartUserId, String username,
			int phaseNumber, Date lastCalcDate) throws SpException {
		try {
			List<UserInStandbyGroup> lsUserInGroup = dto.getLsUsers();
			Long lastTurnUserId = lastStartUserId;

			Collections.sort(lsUserInGroup,
					(UserInStandbyGroup o1, UserInStandbyGroup o2) -> o1.getPosition().compareTo(o2.getPosition()));

			int currentPosition = this.getIndexOfLastPlannedUser(lastStartUserId, lsUserInGroup);
			if (currentPosition == -1) {
				this.createMsgGroupLeaderChanged(userRepository.findOne(lastStartUserId), lsUserInGroup);
				currentPosition = 0;
			}
			Date tmpDate = dto.getStartDate();

			PlanningBodyResultDto planningBodyResultDto = null;
			while (tmpDate.getTime() < dto.getEndDate().getTime()) {

				// reset position if end of list has been reached
				planningBodyResultDto = this.calculateScheduleBodyEntries(lsUserInGroup, dto.getStartDate(), tmpDate,
						lastCalcDate, lastTurnUserId, username, lastStartUserId, phaseNumber);
				tmpDate = planningBodyResultDto.getTempDate();
				currentPosition = planningBodyResultDto.getNewPosition();
				lastStartUserId = planningBodyResultDto.getLastStartUserId();
				lastTurnUserId = planningBodyResultDto.getLastUserId();

				this.addMessagesToList(planningBodyResultDto.getLsMsg());
			}
			planningBodyResultDto.setLastUserId(lastTurnUserId);
			return planningBodyResultDto;
		} catch (Exception e) {
			LOGGER.error(e, e);
			SpErrorEntry ee = SpExceptionEnum.DEFAULT_EXCEPTION.getEntry();
			ee.setE(e);
			throw new SpException(ee);
		}
	}

	/**
	 * Method to create a simple {@link StandbyScheduleBody} object with input
	 * values for planning.
	 * 
	 * @param group
	 * @param username
	 * @param date
	 * @param user
	 * @param duration
	 * @return
	 */
	public StandbyScheduleBody createScheduleBodyObject(StandbyGroup group, String username, Date date, User user,
			StandbyDuration duration, String cause) {
		StandbyScheduleBody stbyBody = new StandbyScheduleBody();
		stbyBody.setModificationDate(new Date());
		stbyBody.setModifiedBy(username);
		stbyBody.setModifiedCause(cause);
		stbyBody.setStandbyGroup(group);
		stbyBody.setUser(user);
		stbyBody.setStatus(standbyStatusRepository.findOne(1l));
		stbyBody.setValidFrom(DateHelper.getDateWithTime(date, duration.getValidFrom()));
		stbyBody.setValidTo(DateHelper.getDateWithTime(date, duration.getValidTo()));

		return stbyBody;
	}

	public List<StandbyScheduleBody> createOverlappingScheduleBodyObjects(StandbyGroup group, String username,
			Date date, User user, StandbyDuration duration, int loopPos, int loopLength) {
		List<StandbyScheduleBody> lsStandbyScheduleBodies = new ArrayList<>();
		StandbyScheduleBody stbyBody = this.createScheduleBodyObject(group, username, date, user, duration,
				TXT_AUTOMATIC_PLANNING);
		if (loopPos > 0) {
			// if not the first loop the schedule body should start at the begin of the day.
			stbyBody.setValidFrom(DateHelper.getDateWithTime(date, DateHelper.getStartOfDay(duration.getValidFrom())));
		}
		Date validTo = DateHelper.getDateWithTime(date, duration.getValidTo());
		validTo = DateHelper.getEndOfDay(validTo);
		stbyBody.setValidTo(validTo);

		stbyBody = this.calculateHoliday(group, date, stbyBody, false);

		lsStandbyScheduleBodies.add(stbyBody);
		if (loopPos + 1 == loopLength) {
			// if last entry use end time of duration
			StandbyScheduleBody stbyBody2 = null;
			stbyBody2 = this.createScheduleBodyObject(group, username, date, user, duration, TXT_AUTOMATIC_PLANNING);
			Date nextDay = DateHelper.addDaysToDate(date, 1);
			Date validFrom = DateHelper.getDateWithTime(DateHelper.addDaysToDate(date, 1),
					DateHelper.getStartOfDay(duration.getValidFrom()));
			stbyBody2.setValidFrom(validFrom);
			validTo = DateHelper.getDateWithTime(nextDay, duration.getValidTo());
			stbyBody2.setValidTo(validTo);
			this.calculateHoliday(group, nextDay, stbyBody2, false);
			lsStandbyScheduleBodies.add(stbyBody2);
		}

		return lsStandbyScheduleBodies;
	}

	/**
	 * Method to check if the current day is a holiday for the standby group and
	 * calls the pre-draw or extend calculation.
	 * 
	 * @param group
	 * @param date
	 * @param stbyBody
	 * @return
	 */
	public StandbyScheduleBody calculateHoliday(StandbyGroup group, Date date, StandbyScheduleBody stbyBody,
			boolean isSingleDay) {
		if (isHoliday(date, group)) {
			if (group.getExtendStandbyTime()) {
				// if extend of standby time is needed
				stbyBody = this.calculateHolidayExtend(group, date, stbyBody);
				if (isSingleDay) { // additional calculation if no day overlapping time slot
					stbyBody = this.calculateHolidayPreDraw(group, date, stbyBody);
				}
			} else {
				// is pre-draw of standby time needed
				stbyBody = this.calculateHolidayPreDraw(group, date, stbyBody);
				if (isSingleDay) { // additional calculation if no day overlapping time slot
					stbyBody = this.calculateHolidayExtend(group, date, stbyBody);
				}
			}
		}
		return stbyBody;
	}

	/**
	 * Method to change the standby time if a holiday / calendar day is defined and
	 * the standby time has to be pre-drawn.
	 * 
	 * @param group
	 * @param date
	 * @param stbyBody
	 * @return
	 */
	public StandbyScheduleBody calculateHolidayPreDraw(StandbyGroup group, Date date, StandbyScheduleBody stbyBody) {

		List<StandbyDuration> lsDurations = this.getFittingDurationsByValidTo(group, date);
		if (lsDurations != null) {
			int size = lsDurations.size();
			// loop backward to find last fitting duration
			for (int a = size; a > 0; a--) {
				StandbyDuration dur = lsDurations.get(a - 1);
				// proof if found duration ends before current body starts.
				if (dur != null && DateHelper.isDateBefore(DateHelper.getDateWithTime(date, dur.getValidTo()),
						stbyBody.getValidFrom())) {
					// set last found duration end as start of current entry
					stbyBody.setValidFrom(DateHelper.getDateWithTime(date, dur.getValidTo()));
					this.createMsgExtendHoliday(stbyBody, date, false);
					// end loop after first fitting result.
					stbyBody.setModifiedCause(TXT_AUTOMATIC_PLANNING_HOLIDAY);
					return stbyBody;
				}
			}
			// no last duration for the day has been found. Therefore the start of day has
			// been used for current entry
			if (DateHelper.isDateBefore(DateHelper.getStartOfDay(date), stbyBody.getValidFrom())) {
				stbyBody.setValidFrom(DateHelper.getDateWithTime(date, DateHelper.getStartOfDay(date)));
				this.createMsgExtendHoliday(stbyBody, date, false);
				stbyBody.setModifiedCause(TXT_AUTOMATIC_PLANNING_HOLIDAY);
			}
		} else {
			// no last duration for the day has been found. Therefore the start of day has
			// been used for current entry
			if (DateHelper.isDateBefore(DateHelper.getStartOfDay(date), stbyBody.getValidFrom())) {
				stbyBody.setValidFrom(DateHelper.getDateWithTime(date, DateHelper.getStartOfDay(date)));
				this.createMsgExtendHoliday(stbyBody, date, false);
				stbyBody.setModifiedCause(TXT_AUTOMATIC_PLANNING_HOLIDAY);
			}
		}

		return stbyBody;
	}

	/**
	 * Method to change the standby time if a holiday / calendar day is defined and
	 * the standby time has to be extended.
	 * 
	 * @param group
	 * @param date
	 * @param stbyBody
	 * @return
	 */
	public StandbyScheduleBody calculateHolidayExtend(StandbyGroup group, Date date, StandbyScheduleBody stbyBody) {
		List<StandbyDuration> lsDurations = this.getFittingDurationsOfGroup(group, date);
		if (lsDurations != null) {
			int size = lsDurations.size();
			// loop forward to find fitting duration that starts after current schedule body
			for (int a = 0; a < size; a++) {
				StandbyDuration dur = lsDurations.get(a);
				// proof if found duration starts after the end of current body.
				if (dur != null && DateHelper.isDateAfter(DateHelper.getDateWithTime(date, dur.getValidFrom()),
						stbyBody.getValidTo())) {
					// set end time of current entry to the start of the next duration
					stbyBody.setValidTo(DateHelper.getDateWithTime(date, dur.getValidFrom()));
					stbyBody.setModifiedCause(TXT_AUTOMATIC_PLANNING_HOLIDAY);
					this.createMsgExtendHoliday(stbyBody, date, true);
					// end loop after first fitting result.
					return stbyBody;
				}
			}
			// no last duration for the day has been found. Therefore the start of day has
			// been used for current entry
			if (DateHelper.isDateAfter(DateHelper.getEndOfDay(date), stbyBody.getValidTo())) {
				stbyBody.setValidTo(DateHelper.getEndOfDay(date));
				stbyBody.setModifiedCause(TXT_AUTOMATIC_PLANNING_HOLIDAY);
				this.createMsgExtendHoliday(stbyBody, date, true);
			}
		} else {
			// no last duration for the day has been found. Therefore the start of day has
			// been used for current entry
			if (DateHelper.isDateAfter(DateHelper.getEndOfDay(date), stbyBody.getValidTo())) {
				stbyBody.setValidTo(DateHelper.getEndOfDay(date));
				stbyBody.setModifiedCause(TXT_AUTOMATIC_PLANNING_HOLIDAY);
				this.createMsgExtendHoliday(stbyBody, date, true);
			}
		}
		return stbyBody;
	}

	public PlanningBodyResultDto calculateScheduleBodyEntries(List<UserInStandbyGroup> lsUserInGroup, Date startDate,
			Date currentDate, Date lastDate, Long lastTurnUserId, String username, Long lastStartUserId,
			int phaseNumber) {
		StandbyGroup group = lsUserInGroup.get(0).getStandbyGroup();
		int currentPosition = this.getIndexOfLastPlannedUser(lastTurnUserId, lsUserInGroup);
		if (currentPosition == -1) {
			currentPosition = 0;
		}
		PlanningBodyResultDto resultObj = new PlanningBodyResultDto();
		resultObj.setLastStartUserId(lastStartUserId);
		resultObj.setNewPosition(currentPosition);
		resultObj.setLastUserId(lsUserInGroup.get(currentPosition).getUser().getId());

		// read fitting duration for the current phase.
		List<StandbyDuration> lsFittingDurations = new ArrayList<>();

		// BP-738 - check if durations are ending at start of phase.
		if (phaseNumber == 1) {
			this.appendEndingDurationsAtStartingPhase(lsFittingDurations, group, startDate, currentDate);
		}
		lsFittingDurations.addAll(this.getFittingDurationsOfGroup(group, currentDate));

		if (!lsFittingDurations.isEmpty()) {
			for (StandbyDuration fittingDuration : lsFittingDurations) {
				int startWeekDayInt = DateHelper.getDayOfWeek(currentDate);
				int endWeekDayInt = fittingDuration.getValidDayTo();
				int coveredDays = DateHelper.calculateDifferenceOfDays(startWeekDayInt, endWeekDayInt,
						fittingDuration.getValidFrom(),
						new DateTime(fittingDuration.getValidTo()).minusSeconds(1).toDate());

				if (coveredDays == 0) {
					// single entry with no over night duration
					LOGGER.debug("A day was found that just cover a single day.");
					StandbyScheduleBody stbyBody = this.createScheduleBodyObject(group, username, currentDate,
							lsUserInGroup.get(currentPosition).getUser(), fittingDuration, TXT_AUTOMATIC_PLANNING);
					standbyScheduleBodyRepository.save(stbyBody);
					// calculate if holiday
					stbyBody = this.calculateHoliday(group, currentDate, stbyBody, true);

					createMsgSavingBody(stbyBody);
				} else {
					resultObj = this.calculateMultiScheduleBodyEntries(lsUserInGroup, currentDate, lastDate,
							currentPosition, username, fittingDuration, coveredDays);
				}
				resultObj.setCurrentDuration(fittingDuration);
				PlanningBodyResultDto resultDto = this.resetCounterToNewPosition(currentPosition, lastStartUserId,
						lsUserInGroup, group.getNextUserInNextCycle(), fittingDuration.getNextUserInNextDuration());
				currentPosition = resultDto.getNewPosition();
				lastStartUserId = resultDto.getLastStartUserId();
				resultObj.setLastStartUserId(lastStartUserId);
			}
			resultObj.setNewPosition(currentPosition);
			resultObj.setTempDate(DateHelper.addDaysToDate(currentDate, 1));
			resultObj.setLastUserId(lsUserInGroup.get(currentPosition).getUser().getId());

		} else {
			resultObj.setTempDate(DateHelper.addDaysToDate(currentDate, 1));
			// this.createMsgNotAvailable(group, currentDate);
		}
		return resultObj;
	}

	public PlanningBodyResultDto calculateMultiScheduleBodyEntries(List<UserInStandbyGroup> lsUserInGroup,
			Date currentDate, Date lastDate, int currentPosition, String username, StandbyDuration fittingDuration,
			int coveredDays) {
		PlanningBodyResultDto resultObj = new PlanningBodyResultDto();
		Date nextDay = null;
		// entries with over night or many days duration
		for (int i = 0; i < coveredDays; i++) {
			nextDay = DateHelper.addDaysToDate(currentDate, 1);
			if (DateHelper.isDateAfter(nextDay, lastDate) || DateHelper.isSameDate(nextDay, lastDate)) {
				StandbyScheduleBody stbyBody = this.createScheduleBodyObject(lsUserInGroup.get(0).getStandbyGroup(),
						username, currentDate, lsUserInGroup.get(currentPosition).getUser(), fittingDuration,
						TXT_AUTOMATIC_PLANNING);
				int dayOfCurrentWeek = DateHelper.getDayOfWeek(currentDate);
				if (dayOfCurrentWeek != DateHelper.getDayOfWeek(new DateTime(lastDate).minusSeconds(1).toDate())
						|| fittingDuration.getValidDayFrom() != dayOfCurrentWeek) {

					// set start of day when it is not the start of the duration and it is not the
					// end of the planning phase
					stbyBody.setValidFrom(DateHelper.getStartOfDay(currentDate));

				}

				// reset ending date to beginning of next day.
				stbyBody.setValidTo(DateHelper.getEndOfDay(currentDate));
				standbyScheduleBodyRepository.save(stbyBody);
				createMsgSavingBody(stbyBody);

				String warning = "Für das Datum (" + currentDate
						+ ") wird der Eintrag nur bis zum Tages-Ende geplant, da der Folgetag den definierten Zeitraum der Phase überschreitet.";
				this.addMessageToList((new PlanningMsgDto(warning, PlanningMsgDto.INFO, PlanningMsgDto.CSS_INFO)));
				resultObj.setNewPosition(currentPosition);
				return resultObj;

			} else {
				List<StandbyScheduleBody> lsScheduleBodies = this.createOverlappingScheduleBodyObjects(
						lsUserInGroup.get(0).getStandbyGroup(), username, currentDate,
						lsUserInGroup.get(currentPosition).getUser(), fittingDuration, i, coveredDays);
				for (StandbyScheduleBody stbyBody : lsScheduleBodies) {
					standbyScheduleBodyRepository.save(stbyBody);
					createMsgSavingBody(stbyBody);
					resultObj.setTempDate(nextDay);
				}
				resultObj.setNewPosition(currentPosition);
				resultObj.setTempDate(nextDay);
				currentDate = resultObj.getTempDate();
			}
		}
		return resultObj;
	}

	/**
	 * Method to create a success message for saving an {@link StandbyScheduleBody}
	 * object.
	 * 
	 * @param stbyBody
	 * @return
	 */
	protected PlanningMsgDto createMsgSavingBody(StandbyScheduleBody stbyBody) {
		String info = stbyBody.getUser().getFirstname() + " " + stbyBody.getUser().getLastname()
				+ " wurde für den Zeitraum vom (" + stbyBody.getValidFrom() + ") bis zum (" + stbyBody.getValidTo()
				+ ") eingeplant.";
		PlanningMsgDto dto = new PlanningMsgDto(info, PlanningMsgDto.INFO, PlanningMsgDto.CSS_INFO_ML3);
		this.addMessageToList(dto);
		return dto;
	}

	/**
	 * Method to create a success message for saving an {@link StandbyScheduleBody}
	 * object.
	 * 
	 * @param stbyBody
	 * @return
	 */
	protected PlanningMsgDto createMsgExtendHoliday(StandbyScheduleBody stbyBody, Date date, Boolean isExtendedDuty) {
		StringBuilder strBuilder = new StringBuilder("Die Bereitschaftszeit für " + stbyBody.getUser().getFirstname()
				+ " " + stbyBody.getUser().getLastname() + " muss am (" + date
				+ ") auf Grund eines dienstfreien Tages");

		if (isExtendedDuty) {
			strBuilder.append(" verlängert werden.");
		} else {
			strBuilder.append(" vorgezogen werden.");
		}

		PlanningMsgDto dto = new PlanningMsgDto(strBuilder.toString(), PlanningMsgDto.INFO, PlanningMsgDto.CSS_INFO);
		this.addMessageToList(dto);
		return dto;
	}

	/**
	 * Method to create a warning because of no given group for planning.
	 * 
	 * @param stbyBody
	 * @return
	 */
	protected PlanningMsgDto createMsgNotAvailable(StandbyGroup group, Date currentDate) {
		String warning = "Für die Gruppe (" + group.getTitle()
				+ ") wurde keine beginnende Duration für folgenden Tag gefunden: (" + currentDate + ")";
		LOGGER.warn(warning);
		PlanningMsgDto dto = new PlanningMsgDto(warning, PlanningMsgDto.WARN, PlanningMsgDto.CSS_WARN);
		this.addMessageToList(dto);
		return dto;
	}

	/**
	 * Method to create a info message with the number of old deleted ScheduleBody
	 * objects.
	 * 
	 * @param map
	 * @param blueprintDto
	 * @return
	 */
	protected PlanningMsgDto createMsgNumberOfPhases(Map<Integer, PlanningPhaseDto> map,
			StandbyScheduleBlueprintDto blueprintDto) {
		String info = "";

		if (map == null || map.size() == 0) {
			info = "Auf Grund fehlender Bereitschaften im gewählten Zeitraum, vom " + blueprintDto.getValidFrom()
					+ " bis " + blueprintDto.getValidTo() + ", konnte keine Bereitschaftsphase generiert werden.";
			LOGGER.info(info);
			PlanningMsgDto dto = new PlanningMsgDto(info, PlanningMsgDto.WARN, PlanningMsgDto.CSS_WARN);
			this.addMessageToList(dto);
			return dto;
		} else {
			// search missing phase slots
			this.addMessagesToList(this.createMsgMissingPhasesFound(map, blueprintDto));

			info = "Durch wechselnde Gruppenmitglieder wurde(n)  " + map.size()
					+ " Bereitschaftsphase(n) für den angegebenen Zeitraum , vom " + blueprintDto.getValidFrom()
					+ " bis " + blueprintDto.getValidTo() + ", erkannt.";
			LOGGER.info(info);
			PlanningMsgDto dto = new PlanningMsgDto(info, PlanningMsgDto.INFO, PlanningMsgDto.CSS_INFO);
			this.addMessageToList(dto);

			return dto;
		}

	}

	protected List<PlanningMsgDto> createMsgStartOfPhase(Integer phaseId, PlanningPhaseDto phase) {
		List<PlanningMsgDto> lsMsgDto = new ArrayList<>();
		String info = "Die Bereitschaftsphase (" + phaseId + ") wird jetzt für den Zeitraum vom ("
				+ DateHelper.getStartOfDay(phase.getStartDate()) + ") bis zum ("
				+ DateHelper.getStartOfDay(phase.getEndDate()) + ") berechnet";
		LOGGER.info(info);
		PlanningMsgDto dto = new PlanningMsgDto(info, PlanningMsgDto.INFO, PlanningMsgDto.CSS_INFO);
		this.addMessageToList(dto);
		lsMsgDto.add(dto);

		StringBuilder builder = new StringBuilder();
		for (UserInStandbyGroup uisg : phase.getLsUsers()) {
			User user = uisg.getUser();
			String name = user.getFirstname() + " " + user.getLastname();
			if (builder.toString().isEmpty()) {
				builder.append(name);
			} else {
				builder.append(", " + name);
			}
		}
		info = "Folgende Bereitschaftende werden verplant: " + builder.toString();
		LOGGER.info(info);
		dto = new PlanningMsgDto(info, PlanningMsgDto.INFO, PlanningMsgDto.CSS_INFO);
		this.addMessageToList(dto);
		lsMsgDto.add(dto);

		return lsMsgDto;
	}

	protected List<PlanningMsgDto> createMsgMissingPhasesFound(Map<Integer, PlanningPhaseDto> map,
			StandbyScheduleBlueprintDto blueprintDto) {
		List<PlanningMsgDto> lsResults = new ArrayList<>();

		Date validFromDate = DateHelper.getStartOfDay(blueprintDto.getValidFrom());
		Date validToDate = DateHelper.getStartOfDay(blueprintDto.getValidTo());
		Date currentDate = null;
		Date lastDate = null;

		for (Entry<Integer, PlanningPhaseDto> entry : map.entrySet()) {
			currentDate = DateHelper.getStartOfDay(entry.getValue().getStartDate());
			// set the validFromDate as lastDate for the first round
			if (entry.getKey().intValue() == 1) {
				lastDate = validFromDate;
			}

			if (!DateHelper.isSameDate(lastDate, currentDate)) {
				String warn = "Es konnte keine Bereitschaftsphase vom (" + currentDate + ") bis zum (" + lastDate
						+ ") berechnet werden, da es in der Bereitschaftsgruppe keine gültigen Mitarbeiter zur Auswahl gibt. "
						+ "Der Plan kann somit für diesen Zeitraum nicht generiert werden.";
				LOGGER.info(warn);
				PlanningMsgDto dto = new PlanningMsgDto(warn, PlanningMsgDto.WARN, PlanningMsgDto.CSS_WARN);
				lsResults.add(dto);
			}

			if (entry.getKey() == map.size()) {
				Date endDate = DateHelper.getStartOfDay(entry.getValue().getEndDate());
				if (DateHelper.isDateBefore(endDate, new DateTime(validToDate).minusDays(1).toDate())) {
					String warn = "Es konnte keine Bereitschaftsphase vom (" + endDate + ") bis zum (" + validToDate
							+ ") berechnet werden, da es in der Bereitschaftsgruppe keine gültigen Mitarbeiter zur Auswahl gibt. "
							+ "Der Plan kann somit für diesen Zeitraum nicht generiert werden.";
					LOGGER.info(warn);
					PlanningMsgDto dto = new PlanningMsgDto(warn, PlanningMsgDto.WARN, PlanningMsgDto.CSS_WARN);
					lsResults.add(dto);
				}

			}
			// refresh last found date
			lastDate = entry.getValue().getEndDate();
			lastDate = DateHelper.getStartOfDay(lastDate);
		}
		return lsResults;
	}

	protected PlanningMsgDto createMsgEndOfPhase(Integer phasenId) {
		String info = "Die Berechnung der Bereitschaftsphase (" + phasenId + ") wurde abgeschlossen";
		LOGGER.info(info);
		PlanningMsgDto dto = new PlanningMsgDto(info, PlanningMsgDto.INFO, PlanningMsgDto.CSS_INFO);
		this.addMessageToList(dto);
		return dto;
	}

	/**
	 * Method to create a info message with the number of old deleted ScheduleBody
	 * objects.
	 * 
	 * @param stbyBody
	 * @return
	 */
	protected PlanningMsgDto createMsgLeaveOutStarter() {
		String info = "Der letzte Starter wurde aufgrund des aktivierten Vorschubs übersprungen.";
		LOGGER.info(info);
		PlanningMsgDto dto = new PlanningMsgDto(info, PlanningMsgDto.INFO, PlanningMsgDto.CSS_INFO);
		this.addMessageToList(dto);
		return dto;
	}

	/**
	 * Method to create a info message with the number of old deleted ScheduleBody
	 * objects.
	 * 
	 * @param stbyBody
	 * @return
	 */
	protected PlanningMsgDto createMsgDeleteScheduleBodies(int numberOfElements) {
		String warning = "Es wurden " + numberOfElements
				+ " ältere Bereitschaften für den angegebenen Zeitraum entfernt.";
		LOGGER.info(warning);
		PlanningMsgDto dto = new PlanningMsgDto(warning, PlanningMsgDto.WARN, PlanningMsgDto.CSS_WARN);
		this.addMessageToList(dto);
		return dto;
	}

	/**
	 * Method to create a info message with the number of old deleted ScheduleBody
	 * objects.
	 * 
	 * @param stbyBody
	 * @return
	 */
	protected PlanningMsgDto createMsgGroupLeaderChanged(User user, List<UserInStandbyGroup> lsUserInStandbyGroup) {
		User nextUser = lsUserInStandbyGroup.get(0).getUser();
		String warning = "Die ausgewählte Start - Bereitschaft (" + user.getFirstname() + " " + user.getLastname()
				+ ") ist im angegebenen Zeitraum nicht aktiv. Es wird mit (" + nextUser.getFirstname() + " "
				+ nextUser.getLastname() + ") begonnen.";
		LOGGER.info(warning);
		PlanningMsgDto dto = new PlanningMsgDto(warning, PlanningMsgDto.WARN, PlanningMsgDto.CSS_WARN);
		this.addMessageToList(dto);
		return dto;
	}

	/**
	 * Method to delete {@link StandbyScheduleBody} Objects by a list of id's.
	 * 
	 * @param lsIds
	 * @return
	 */
	public PlanningMsgDto deleteScheduleBodiesByIds(List<Long> lsIds) throws SpException {
		try {
			for (Long id : lsIds) {
				standbyScheduleBodyRepository.delete(id);
			}
			return createMsgDeleteScheduleBodies(lsIds.size());
		} catch (Exception e) {
			SpErrorEntry ee = SpExceptionEnum.COULD_NOT_DELETE_ENTITY_EXCEPTION.getEntry();
			ee.setMessage(MessageFormat.format(ee.getMessage(), "StandbyScheduleBodies", e.getMessage()));
			SpException spE = new SpException(ee);
			LOGGER.error(spE, spE);
			throw spE;
		}
	}

	/**
	 * Method to check if date is a defined value in calendar database.
	 * 
	 * @param date
	 * @return
	 */
	public Boolean isHoliday(Date date, StandbyGroup group) {
		DateTime endTime = new DateTime(DateHelper.getEndOfDay(date));
		endTime = endTime.minus(100);
		List<CalendarDay> lsCalendarDays = calendarRepository.findValidByDate(DateHelper.getStartOfDay(date),
				endTime.toDate());
		if (lsCalendarDays != null && !lsCalendarDays.isEmpty()) {
			List<CalendarDay> lsIgnoreList = group.getLsIgnoredCalendarDays();
			for (CalendarDay day : lsCalendarDays) {
				if (!lsIgnoreList.contains(day)) {
					return true;
				}
			}
			return false;
		} else {
			return false;
		}
	}

	/**
	 * Method to get the start duration time for the group.
	 * 
	 * @param group
	 * @param date
	 * @return null if no fitting duration is available
	 */
	public StandbyDuration getFittingDurationOfGroup(StandbyGroup group, Date date) {
		List<StandbyDuration> lsDuration = this.getFittingDurationsOfGroup(group, date);
		if (lsDuration != null && !lsDuration.isEmpty()) {
			return lsDuration.get(0);
		}
		return null;
	}

	/**
	 * Method to get the start duration time for the group.
	 * 
	 * @param group
	 * @param date
	 * @return null if no fitting duration is available
	 */
	public List<StandbyDuration> getFittingDurationsOfGroup(StandbyGroup group, Date date) {
		int dayOfWeek = DateHelper.getDayOfWeek(date);
		return standbyDurationRepository.findDurationForValidFromDay(group.getId(), dayOfWeek);
	}

	/**
	 * Method to get the start duration time for the group.
	 * 
	 * @param group
	 * @param date
	 * @return null if no fitting duration is available
	 */
	public StandbyDuration getFittingDurationByValidTo(StandbyGroup group, Date date) {
		List<StandbyDuration> lsDuration = this.getFittingDurationsByValidTo(group, date);
		if (lsDuration != null && !lsDuration.isEmpty()) {
			return lsDuration.get(lsDuration.size() - 1);
		}
		return null;
	}

	/**
	 * Method to get a list of {@link StandbyDuration} by its end time for the
	 * group.
	 * 
	 * @param group
	 * @param date
	 * @return null if no fitting duration is available
	 */
	public List<StandbyDuration> getFittingDurationsByValidTo(StandbyGroup group, Date endDate) {
		int dayOfWeek = DateHelper.getDayOfWeek(endDate);
		return standbyDurationRepository.findDurationForValidToDay(group.getId(), dayOfWeek);
	}

	/**
	 * Method to get a list of {@link StandbyDuration} where the time is around the
	 * searched date. startOfDuration <= searchedDate <= endDate
	 * 
	 * @param group
	 * @param date
	 * @return null if no fitting duration is available
	 */
	public List<StandbyDuration> getFittingDurationsAroundDate(StandbyGroup group, Date date) {
		int dayOfWeek = DateHelper.getDayOfWeek(date);
		List<StandbyDuration> lsFittingDurations = new ArrayList<>();
		List<StandbyDuration> lsDurations = standbyDurationRepository.findById(group.getId());
		for (StandbyDuration dur : lsDurations) {
			if (dur.getValidDayFrom() <= dayOfWeek && dayOfWeek <= dur.getValidDayTo()) {
				// start <= current <= end
				lsFittingDurations.add(dur);
			} else if (dur.getValidDayFrom() > dur.getValidDayTo()) {
				// start > end
				int calcValue = dayOfWeek;
				if (dur.getValidDayFrom() > dayOfWeek) {
					// AND start > current
					calcValue = dayOfWeek + 7;
				}
				if (dur.getValidDayFrom() < calcValue && calcValue <= (dur.getValidDayTo() + 7)) {
					lsFittingDurations.add(dur);
				}
			} else if (dur.getValidDayFrom() == dur.getValidDayTo() && (dur.getValidDayFrom() == dayOfWeek
					|| DateHelper.calculateDifferenceOfDays(dur.getValidDayFrom(), dur.getValidDayTo(),
							dur.getValidFrom(), dur.getValidTo()) == 7)) {
				// if same day of week or if whole week
				lsFittingDurations.add(dur);
			}
		}
		return lsFittingDurations;
	}

	/**
	 * Method to set the currentPosition to 0 if end of list is reached.
	 * 
	 * @param currentPosition
	 * @param listSize
	 * @return
	 */
	public PlanningBodyResultDto resetCounterToNewPosition(int currentPosition, Long lastStartUserId,
			List<UserInStandbyGroup> lsUserInGroup, Boolean isNextUserInNextCycle, Boolean isNextUserInNextDuration) {
		LOGGER.debug("currentPosition: " + currentPosition);
		LOGGER.debug("lastStartUserId: " + lastStartUserId);
		LOGGER.debug("UserList Size: " + lsUserInGroup.size());

		// default values
		PlanningBodyResultDto result = new PlanningBodyResultDto();
		result.setLastStartUserId(lastStartUserId);
		result.setNewPosition(currentPosition);

		if (isNextUserInNextDuration) {
			// get next available position
			currentPosition = this.getNextAvailablePosition(currentPosition, lsUserInGroup);
			LOGGER.debug("next currentPosition is: " + currentPosition);
			int lastIndex = this.getIndexOfLastPlannedUser(lastStartUserId, lsUserInGroup);
			LOGGER.debug("lastIndexOf: " + lastIndex);
			if (currentPosition == lastIndex) {
				LOGGER.debug("start user found at current position " + currentPosition);
				if (isNextUserInNextCycle) {
					LOGGER.debug("Because of isNextUserInNextCycle = '" + isNextUserInNextCycle
							+ "' next position will be searched...) ");
					this.createMsgLeaveOutStarter();
					currentPosition = this.getNextAvailablePosition(currentPosition, lsUserInGroup);
					LOGGER.debug("next currentPosition is: " + currentPosition);
					Long nextStartUserId = lsUserInGroup.get(currentPosition).getUser().getId();
					result.setLastStartUserId(nextStartUserId);
					LOGGER.debug("Next start user id is set to :" + nextStartUserId.longValue());
				} else {
					LOGGER.debug("Because of isNextUserInNextCycle = '" + isNextUserInNextCycle
							+ "' currentPosition is still: " + currentPosition);
				}
			}
		} else {
			LOGGER.info("isNextUserInNextDuration == false. CurrentUser still in charge.");
		}
		result.setNewPosition(currentPosition);
		return result;
	}

	/**
	 * Method to calculate the next available position in array list. Starts with
	 * the first on if list has reached the end.
	 * 
	 * @param currentPosition
	 * @param lsUserInGroup
	 * @return
	 */
	public int getNextAvailablePosition(int currentPosition, List<UserInStandbyGroup> lsUserInGroup) {
		if (currentPosition + 1 < lsUserInGroup.size()) {
			return currentPosition + 1;
		} else {
			return 0;
		}
	}

	/**
	 * Method to get the position of the last planned user. Returns back '-1' if not
	 * found in given list.
	 * 
	 * @param currentPosition
	 * @param listSize
	 * @return
	 */
	public int getIndexOfLastPlannedUser(Long lastStartUserId, List<UserInStandbyGroup> lsUserInGroup) {
		int indexOf = -1;
		for (UserInStandbyGroup userInGroup : lsUserInGroup) {
			if (userInGroup.getUser().getId().longValue() == lastStartUserId.longValue()) {
				indexOf = lsUserInGroup.indexOf(userInGroup);
				return indexOf;
			}
		}
		return indexOf;
	}

	/**
	 * Method to validate the input parameter for the planning.
	 * 
	 * @param standbyBlueprintDto
	 * @return
	 * @throws SpException
	 */
	public boolean validateInputForPlanCalculation(StandbyScheduleBlueprintDto standbyBlueprintDto) throws SpException {
		if (standbyBlueprintDto.getStandbyListId() != null) {
			if (!standbyListRepository.exists(standbyBlueprintDto.getStandbyListId())) {
				SpErrorEntry ee = SpExceptionEnum.UNKNOWN_ENTITY_EXCEPTION.getEntry();
				String txt = MessageFormat.format(SpMsg.TXT_STANDBY_LIST_WITH_ID,
						standbyBlueprintDto.getStandbyListId());
				ee.setMessage(MessageFormat.format(ee.getMessage(), txt));
				SpException spE = new SpException(ee);
				LOGGER.error(spE, spE);
				throw spE;
			}
		} else {
			SpErrorEntry ee = SpExceptionEnum.MISSING_PARAMETER_EXCEPTION.getEntry();
			ee.setMessage(MessageFormat.format(ee.getMessage(), "StandbyList"));
			SpException spE = new SpException(ee);
			LOGGER.error(spE, spE);
			throw spE;
		}

		if (standbyBlueprintDto.getStandbyGroupId() != null) {
			if (!standbyGroupRepository.exists(standbyBlueprintDto.getStandbyGroupId())) {
				SpErrorEntry ee = SpExceptionEnum.UNKNOWN_ENTITY_EXCEPTION.getEntry();
				String txt = MessageFormat.format(SpMsg.TXT_STANDBY_GROUP_WITH_ID,
						standbyBlueprintDto.getStandbyGroupId());
				ee.setMessage(MessageFormat.format(ee.getMessage(), txt));
				SpException spE = new SpException(ee);
				LOGGER.error(spE, spE);
				throw spE;
			}
		} else {
			SpErrorEntry ee = SpExceptionEnum.MISSING_PARAMETER_EXCEPTION.getEntry();
			ee.setMessage(MessageFormat.format(ee.getMessage(), "StandbyGroup"));
			SpException spE = new SpException(ee);
			LOGGER.error(spE, spE);
			throw spE;
		}

		if (standbyBlueprintDto.getValidFrom() == null) {
			SpErrorEntry ee = SpExceptionEnum.MISSING_PARAMETER_EXCEPTION.getEntry();
			ee.setMessage(MessageFormat.format(ee.getMessage(), "validFrom"));
			SpException spE = new SpException(ee);
			LOGGER.error(spE, spE);
			throw spE;
		}

		if (standbyBlueprintDto.getValidTo() == null) {
			SpErrorEntry ee = SpExceptionEnum.MISSING_PARAMETER_EXCEPTION.getEntry();
			ee.setMessage(MessageFormat.format(ee.getMessage(), "validTo"));
			SpException spE = new SpException(ee);
			LOGGER.error(spE, spE);
			throw spE;
		}

		return true;
	}

	/**
	 * Method to log the phase map object.
	 * 
	 * @param resultMap
	 */
	public void logPhases(Map<Integer, PlanningPhaseDto> resultMap) {
		LOGGER.debug("The following " + resultMap.keySet().size() + " had been found");
		for (Entry<Integer, PlanningPhaseDto> entry : resultMap.entrySet()) {
			LOGGER.debug("-----------------------");
			LOGGER.debug("Phase :" + entry.getKey());
			LOGGER.debug("-----------------------");
			PlanningPhaseDto dto = entry.getValue();
			LOGGER.debug("StartDate :" + dto.getStartDate());
			LOGGER.debug("EndDate :" + dto.getEndDate());
			LOGGER.debug("Number of StandbyUser :" + dto.getLsUsers().size());
			for (UserInStandbyGroup uisg : dto.getLsUsers()) {
				LOGGER.debug("Gruppenmitglied :" + uisg.getUser().getFirstname() + " " + uisg.getUser().getLastname());
			}
		}
	}

	/**
	 * Method to replace user in schedule bodies for the given interval
	 * 
	 * @param actionDto
	 * @param username
	 * @return
	 * @throws SpException
	 */
	public PlanningMsgResponseDto replaceUserInPlan(StandbyScheduleActionDto actionDto, String username)
			throws SpException {
		PlanningMsgResponseDto responseDto = new PlanningMsgResponseDto();
		this.startWithNewList();

		// check input values
		List<Object> lsInputParams = new ArrayList<>();
		lsInputParams.add(actionDto.getCurrentUserId());
		lsInputParams.add(actionDto.getNewUserId());
		lsInputParams.add(actionDto.getStandbyGroupId());
		lsInputParams.add(actionDto.getStatusId());
		lsInputParams.add(actionDto.getValidFrom());
		lsInputParams.add(actionDto.getValidTo());
		lsInputParams.add(username);
		ValidationHelper.isNoNullValueInList(lsInputParams);

		try {

			// history
			archiveController.createArchiveOnReplaceInOneGroup(actionDto, username);

			User currentUser = userRepository.findOne(actionDto.getCurrentUserId());
			User newUser = userRepository.findOne(actionDto.getNewUserId());
			StandbyGroup standbyGroup = standbyGroupRepository.findOne(actionDto.getStandbyGroupId());
			Date from = actionDto.getValidFrom();
			Date to = actionDto.getValidTo();

			// mail
			mailing.replaceMessage1(actionDto, currentUser, newUser, standbyGroup);
			mailing.replaceMessage2(actionDto, currentUser, newUser, standbyGroup);

			ArrayList<StandbyGroup> lsStandbyGroups = new ArrayList<>();
			List<StandbyScheduleBody> lsBodies = standbyScheduleBodyRepository.findByUserAndGroupAndDateAndStatus(
					currentUser.getId(), actionDto.getStandbyGroupId(), DateHelper.getStartOfDay(from),
					DateHelper.getEndOfDay(to), actionDto.getStatusId());

			for (StandbyScheduleBody body : lsBodies) {
				this.splitScheduleBody(body, from, to, newUser, username);
				if (!lsStandbyGroups.contains(body.getStandbyGroup())) {
					lsStandbyGroups.add(body.getStandbyGroup());
				}
			}

			// start validation
			List<String> lsValidationBeanNames = new ArrayList<>();
			lsValidationBeanNames.add(ValidationController.BEAN_USER_AVAILABLE_VALIDATOR);
			lsValidationBeanNames.add(ValidationController.BEAN_USER_AVAILABLE_FOR_GROUP_VALIDATOR);
			lsValidationBeanNames.add(ValidationController.BEAN_GROUP_COVERAGE_VALIDATOR);
			lsValidationBeanNames.add(ValidationController.BEAN_DOUBLE_PLANNED_VALIDATOR);
			lsValidationBeanNames.add(ValidationController.BEAN_PLACEHOLDER_STANDBY_USER_VALIDATOR);

			responseDto.getLsMsg()
					.addAll(validatonController.startValidation(actionDto.getValidFrom(), actionDto.getValidTo(),
							lsStandbyGroups, lsValidationBeanNames, actionDto.getStatusId(), actionDto.getNewUserId()));

			return responseDto;
		} catch (Exception e) {
			LOGGER.error(e, e);
			SpErrorEntry ee = SpExceptionEnum.DEFAULT_EXCEPTION.getEntry();
			ee.setE(e);
			throw new SpException(ee);
		}
	}

	protected Boolean splitScheduleBody(StandbyScheduleBody body, Date from, Date to, User newUser, String modifiedBy)
			throws SpException {
		try {
			Date tmpFrom = from;
			Date tmpTo = to;
			if (DateHelper.isDateBefore(from, DateHelper.getStartOfDay(body.getValidFrom()))) {
				tmpFrom = DateHelper.getStartOfDay(body.getValidFrom());
			}

			if (DateHelper.isDateAfter(to, DateHelper.getEndOfDay(body.getValidFrom()))) {
				tmpTo = DateHelper.getEndOfDay(body.getValidFrom());
			}

			// interval of ui params
			Interval intervalSelection = new Interval(new DateTime(tmpFrom).getMillis(),
					new DateTime(tmpTo).getMillis());

			// interval of saved schedule body
			Interval intervalBody = new Interval(new DateTime(body.getValidFrom()).getMillis(),
					new DateTime(body.getValidTo()).getMillis());

			// overlapping interval between params and schedule body values
			Interval intervalOverlap = intervalBody.overlap(intervalSelection);

			if (intervalOverlap != null) {
				int isSameStart = DateHelper.isSameDateTime(body.getValidFrom(), tmpFrom);
				int isSameEnd = DateHelper.isSameDateTime(body.getValidTo(), tmpTo);

				tmpFrom = intervalOverlap.getStart().toDate();
				tmpTo = intervalOverlap.getEnd().toDate();
				if (isSameStart >= 0) {
					if (isSameEnd == 0) {
						// full replace
						body.setUser(newUser);
						body.setModifiedCause(TXT_MANUAL_CHANGE);
						body.setModificationDate(new Date());
						body.setModifiedBy(modifiedBy);
						standbyScheduleBodyRepository.save(body);
					} else if (isSameEnd < 0) {
						body.setUser(newUser);
						body.setModifiedCause(TXT_MANUAL_CHANGE);
						body.setModificationDate(new Date());
						body.setModifiedBy(modifiedBy);
						body.setValidTo(tmpTo);
						standbyScheduleBodyRepository.save(body);
					} else {
						StandbyScheduleBody newBody = body.copy();
						newBody.setUser(newUser);
						newBody.setModifiedCause(TXT_MANUAL_CHANGE);
						newBody.setModificationDate(new Date());
						newBody.setModifiedBy(modifiedBy);
						newBody.setValidTo(tmpTo);
						standbyScheduleBodyRepository.save(newBody);

						body.setValidFrom(tmpTo);
						body.setModifiedCause(TXT_MANUAL_CHANGE);
						body.setModificationDate(new Date());
						body.setModifiedBy(modifiedBy);
						standbyScheduleBodyRepository.save(body);
					}
				} else if (isSameEnd == 0) {
					StandbyScheduleBody newBody = body.copy();
					newBody.setUser(newUser);
					newBody.setModifiedCause(TXT_MANUAL_CHANGE);
					newBody.setModificationDate(new Date());
					newBody.setModifiedBy(modifiedBy);
					newBody.setValidFrom(tmpFrom);
					standbyScheduleBodyRepository.save(newBody);

					body.setValidTo(tmpFrom);
					body.setModifiedCause(TXT_MANUAL_CHANGE);
					body.setModificationDate(new Date());
					body.setModifiedBy(modifiedBy);
					standbyScheduleBodyRepository.save(body);
				} else if (isSameEnd < 0) {
					// replace with end at 23:59
					StandbyScheduleBody newBody = body.copy();
					newBody.setUser(newUser);
					newBody.setModifiedCause(TXT_MANUAL_CHANGE);
					newBody.setModificationDate(new Date());
					newBody.setModifiedBy(modifiedBy);
					newBody.setValidFrom(tmpFrom);
					newBody.setValidTo(tmpTo);
					standbyScheduleBodyRepository.save(newBody);

					body.setModifiedCause(TXT_MANUAL_CHANGE);
					body.setModificationDate(new Date());
					body.setModifiedBy(modifiedBy);
					body.setValidTo(tmpFrom);
					standbyScheduleBodyRepository.save(body);
				} else {
					// set new user (n1) between old (o1) existing entry by splitting it.
					// Looks like this [o1--n1--o2]
					StandbyScheduleBody newBody = body.copy();
					newBody.setUser(newUser);
					newBody.setModifiedCause(TXT_MANUAL_CHANGE);
					newBody.setModificationDate(new Date());
					newBody.setModifiedBy(modifiedBy);
					newBody.setValidFrom(tmpFrom);
					newBody.setValidTo(tmpTo);
					standbyScheduleBodyRepository.save(newBody);

					// set new entry to not loose the time after
					StandbyScheduleBody oldBodyAfter = body.copy();
					oldBodyAfter.setModifiedCause(TXT_MANUAL_CHANGE);
					oldBodyAfter.setModificationDate(new Date());
					oldBodyAfter.setModifiedBy(modifiedBy);
					oldBodyAfter.setValidFrom(tmpTo);
					standbyScheduleBodyRepository.save(oldBodyAfter);

					// set
					body.setModifiedCause(TXT_MANUAL_CHANGE);
					body.setModificationDate(new Date());
					body.setModifiedBy(modifiedBy);
					body.setValidTo(tmpFrom);
					standbyScheduleBodyRepository.save(body);
				}
			}

			return true;
		} catch (Exception e) {
			LOGGER.error(e, e);
			SpErrorEntry ee = SpExceptionEnum.DEFAULT_EXCEPTION.getEntry();
			ee.setE(e);
			throw new SpException(ee);
		}
	}

	/**
	 * Method to change the time of a schedule body.
	 * 
	 * @param actionDto
	 * @param username
	 * @return
	 * @throws SpException
	 */
	public PlanningMsgResponseDto moveUserInPlan(StandbyScheduleActionDto actionDto, String username)
			throws SpException {
		PlanningMsgResponseDto responseDto = new PlanningMsgResponseDto();
		this.startWithNewList();

		// check input values
		List<Object> lsInputParams = new ArrayList<>();
		lsInputParams.add(actionDto.getNewUserId());
		lsInputParams.add(actionDto.getScheduleBodyId());
		lsInputParams.add(actionDto.getValidFrom());
		lsInputParams.add(actionDto.getValidTo());
		lsInputParams.add(actionDto.getStandbyGroupId());
		lsInputParams.add(username);
		ValidationHelper.isNoNullValueInList(lsInputParams);

		StandbyGroup tempOldGroup = null;
		StandbyGroup tempNewGroup = null;

		try {

			// history
			archiveController.createArchiveOnMove(actionDto, username);

			StandbyScheduleBody body = standbyScheduleBodyRepository.findOne(actionDto.getScheduleBodyId());
			tempNewGroup = standbyGroupRepository.findOne(actionDto.getStandbyGroupId());

			// mail
			mailing.moveMessage1(actionDto, body, tempNewGroup);

			tempOldGroup = body.getStandbyGroup();
			body.setModifiedCause(SpMsg.ACT_STANDBY_MOVE);
			body.setModificationDate(new Date());
			body.setModifiedBy(username);
			body.setStandbyGroup(tempNewGroup);

			DateTime dt = new DateTime(actionDto.getValidTo());
			if (DateHelper.isSameDate(actionDto.getValidFrom(), dt.minusSeconds(1).toDate())) {
				// because of no overlapping day schedule body just
				// gets new values, no second body is needed.
				body.setValidFrom(actionDto.getValidFrom());
				body.setValidTo(actionDto.getValidTo());
				standbyScheduleBodyRepository.save(body);

			} else {
				Date nextDate = actionDto.getValidFrom();
				StandbyScheduleBody newBody = null;
				while (DateHelper.isDateBefore(nextDate, actionDto.getValidTo())
						&& !DateHelper.isSameDate(nextDate, actionDto.getValidTo())) {
					newBody = body.copy();
					if (DateHelper.isSameDate(actionDto.getValidFrom(), nextDate)) {
						// do not change start time on first day
						newBody.setValidFrom(nextDate);
					} else {
						// begin with = 0:00 if not first day
						newBody.setValidFrom(DateHelper.getStartOfDay(nextDate));
					}
					newBody.setValidTo(DateHelper.getEndOfDay(nextDate));
					newBody.setModifiedCause(TXT_MANUAL_CHANGE);
					newBody.setModificationDate(new Date());
					newBody.setModifiedBy(username);
					newBody.setStandbyGroup(body.getStandbyGroup());
					standbyScheduleBodyRepository.save(newBody);

					nextDate = DateHelper.addDaysToDate(nextDate, 1);
				}

				// add last day
				StandbyScheduleBody lastBody = body.copy();
				lastBody.setValidFrom(DateHelper.getStartOfDay(actionDto.getValidTo()));
				lastBody.setValidTo(actionDto.getValidTo());
				lastBody.setModifiedCause(TXT_MANUAL_CHANGE);
				lastBody.setModificationDate(new Date());
				lastBody.setModifiedBy(username);
				lastBody.setStandbyGroup(body.getStandbyGroup());
				standbyScheduleBodyRepository.save(lastBody);

				// remove original because of splitting it to multiple entries
				standbyScheduleBodyRepository.delete(body.getId());
			}

			ArrayList<StandbyGroup> lsStandbyGroups = new ArrayList<>();
			lsStandbyGroups.add(tempOldGroup);
			// add new group to check list if it differs from origin group
			if (tempOldGroup.getId().longValue() != tempNewGroup.getId().longValue()) {
				lsStandbyGroups.add(tempNewGroup);
			}

			// start validation
			List<String> lsValidationBeanNames = new ArrayList<>();
			lsValidationBeanNames.add(ValidationController.BEAN_USER_AVAILABLE_VALIDATOR);
			lsValidationBeanNames.add(ValidationController.BEAN_USER_AVAILABLE_FOR_GROUP_VALIDATOR);
			lsValidationBeanNames.add(ValidationController.BEAN_GROUP_COVERAGE_VALIDATOR);
			lsValidationBeanNames.add(ValidationController.BEAN_DOUBLE_PLANNED_VALIDATOR);
			lsValidationBeanNames.add(ValidationController.BEAN_PLACEHOLDER_STANDBY_USER_VALIDATOR);
			responseDto.getLsMsg()
					.addAll(validatonController.startValidation(actionDto.getValidFrom(), actionDto.getValidTo(),
							lsStandbyGroups, lsValidationBeanNames, actionDto.getStatusId(), actionDto.getNewUserId()));

			return responseDto;
		} catch (Exception e) {
			LOGGER.error(e, e);
			SpErrorEntry ee = SpExceptionEnum.DEFAULT_EXCEPTION.getEntry();
			ee.setE(e);
			throw new SpException(ee);
		}
	}

	/**
	 * Method to search for durations that will end at the day the current phase is
	 * starting. Therefore maybe the end of durations that are starting the day
	 * before will be found.
	 * 
	 * @param lsFittingDurations
	 * @param group
	 * @param startDate
	 * @param currentDate
	 * @return
	 */
	private List<StandbyDuration> appendEndingDurationsAtStartingPhase(List<StandbyDuration> lsFittingDurations,
			StandbyGroup group, Date startDate, Date currentDate) {
		// Only at the start of a new phase the ending durations have to be used, too.
		if (startDate.equals(currentDate)) {
			List<StandbyDuration> lsFittingDurationsEndingAtStart = this.getFittingDurationsAroundDate(group,
					currentDate);
			if (lsFittingDurationsEndingAtStart != null && !lsFittingDurationsEndingAtStart.isEmpty()) {
				for (StandbyDuration dur : lsFittingDurationsEndingAtStart) {
					int startWeekDayInt = DateHelper.getDayOfWeek(currentDate);
					int endDurationWeekDayInt = dur.getValidDayTo();

					int coveredDays = DateHelper.calculateDifferenceOfDays(startWeekDayInt, endDurationWeekDayInt,
							dur.getValidFrom(), dur.getValidTo());
					if (coveredDays != 0) {
						// only durations should be added that start at least one day before and their
						// ending at the phase start
						StandbyDuration tmpDuration = dur.copy();
						tmpDuration.setValidFrom(DateHelper.getStartOfDay(tmpDuration.getValidFrom()));
						tmpDuration.setValidDayFrom(DateHelper.getDayOfWeek(currentDate));
						tmpDuration.setValidDayTo(DateHelper.getDayOfWeek(currentDate));
						lsFittingDurations.add(tmpDuration);
					}
				}
			}
		}
		return lsFittingDurations;
	}

	/**
	 * Method to add PlanningMsgDtos to list and stop filling the list at an amount
	 * bigger then 200 entries.
	 */
	public void addMessagesToList(List<PlanningMsgDto> lsMsg) {
		for (PlanningMsgDto dto : lsMsg) {
			if (dto.getType().equals(PlanningMsgDto.INFO)) {
				lsPlanningMsg.add(dto);
			} else if (warningCounter < 200) {
				lsPlanningMsg.add(dto);
				warningCounter++;
			} else {
				PlanningMsgDto lastDto = lsPlanningMsg.get(lsPlanningMsg.size() - 1);
				if (!lastDto.getMsg().equals(TXT_AND_MORE)) {
					lsPlanningMsg.add(new PlanningMsgDto(TXT_AND_MORE, PlanningMsgDto.WARN, PlanningMsgDto.CSS_WARN));
				}
			}
		}
	}

	/**
	 * Method to add a PlanningMsgDto to list.
	 */
	public void addMessageToList(PlanningMsgDto msg) {
		List<PlanningMsgDto> lsMsg = new ArrayList<>();
		lsMsg.add(msg);
		this.addMessagesToList(lsMsg);
	}

	public List<PlanningMsgDto> getLsMsgDto() {
		return lsPlanningMsg;
	}

	public void startWithNewList() {
		lsPlanningMsg = new ArrayList<>();
		warningCounter = 0;
	}

	public int getWarningCounter() {
		return warningCounter;
	}
}
