package de.ph87.homeautomation.schedule.entry; import de.ph87.homeautomation.bulk.BulkReader; import de.ph87.homeautomation.property.PropertyReader; import de.ph87.homeautomation.schedule.Schedule; import de.ph87.homeautomation.schedule.ScheduleReader; import de.ph87.homeautomation.schedule.ScheduleWriter; import de.ph87.homeautomation.web.BadRequestException; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.function.BiConsumer; import java.util.function.Consumer; import static java.lang.Integer.signum; import static java.lang.Math.max; import static java.lang.Math.min; @Slf4j @Service @Transactional @RequiredArgsConstructor public class ScheduleEntryWriter { private final ScheduleEntryReader scheduleEntryReader; private final ScheduleReader scheduleReader; private final ScheduleEntryMapper scheduleEntryMapper; private final ScheduleEntryRepository scheduleEntryRepository; private final PropertyReader propertyReader; private final BulkReader bulkReader; private final ScheduleWriter scheduleWriter; public ScheduleEntryDto create(final long scheduleId) { final Schedule schedule = scheduleReader.getById(scheduleId); final ScheduleEntry entry = scheduleEntryRepository.save(new ScheduleEntry(schedule)); schedule.getEntries().add(entry); scheduleWriter.notifyChanged(schedule); return scheduleEntryMapper.toDto(entry); } private ScheduleEntryDto modifyValue(final long id, final BiConsumer setter, final T value) { return modify(id, entry -> setter.accept(entry, value)); } private ScheduleEntryDto modify(final long id, final Consumer setter) { final ScheduleEntry entry = scheduleEntryReader.getById(id); setter.accept(entry); scheduleWriter.notifyChanged(entry.getSchedule()); return scheduleEntryMapper.toDto(entry); } public void delete(final long id) { final ScheduleEntry entry = scheduleEntryReader.getById(id); setPosition(entry, entry.getSchedule().getEntries().size() - 1); entry.getSchedule().getEntries().remove(entry); scheduleEntryRepository.delete(entry); scheduleWriter.notifyChanged(entry.getSchedule()); } public ScheduleEntryDto setPosition(final long id, final int newPosition) { return modify(id, entry -> { if (newPosition < 0 || newPosition >= entry.getSchedule().getEntries().size()) { throw new BadRequestException("Position must be between 0 and %d (including).", entry.getSchedule().getEntries().size() - 1); } setPosition(entry, newPosition); }); } public ScheduleEntryDto setEnabled(final long id, final boolean value) { return modifyValue(id, ScheduleEntry::setEnabled, value); } public ScheduleEntryDto setMonday(final long id, final boolean value) { return modifyValue(id, ScheduleEntry::setMonday, value); } public ScheduleEntryDto setTuesday(final long id, final boolean value) { return modifyValue(id, ScheduleEntry::setTuesday, value); } public ScheduleEntryDto setWednesday(final long id, final boolean value) { return modifyValue(id, ScheduleEntry::setWednesday, value); } public ScheduleEntryDto setThursday(final long id, final boolean value) { return modifyValue(id, ScheduleEntry::setThursday, value); } public ScheduleEntryDto setFriday(final long id, final boolean value) { return modifyValue(id, ScheduleEntry::setFriday, value); } public ScheduleEntryDto setSaturday(final long id, final boolean value) { return modifyValue(id, ScheduleEntry::setSaturday, value); } public ScheduleEntryDto setSunday(final long id, final boolean value) { return modifyValue(id, ScheduleEntry::setSunday, value); } public ScheduleEntryDto setType(final long id, final ScheduleEntryType value) { return modifyValue(id, ScheduleEntry::setType, value); } public ScheduleEntryDto setZenith(final long id, final double value) { return modifyValue(id, ScheduleEntry::setZenith, value); } public ScheduleEntryDto setHour(final long id, final int value) { return modifyValue(id, ScheduleEntry::setHour, value); } public ScheduleEntryDto setMinute(final long id, final int value) { return modifyValue(id, ScheduleEntry::setMinute, value); } public ScheduleEntryDto setSecond(final long id, final int value) { return modifyValue(id, ScheduleEntry::setSecond, value); } public ScheduleEntryDto setFuzzySeconds(final long id, final int value) { return modifyValue(id, ScheduleEntry::setFuzzySeconds, value); } public ScheduleEntryDto setValue(final long id, final double value) { return modifyValue(id, ScheduleEntry::setValue, value); } public ScheduleEntryDto setProperty(final long id, final Long propertyId) { return modifyValue(id, ScheduleEntry::setProperty, propertyId == null ? null : propertyReader.getById(propertyId)); } public ScheduleEntryDto setBulk(final long id, final Long bulkId) { return modifyValue(id, ScheduleEntry::setBulk, bulkId == null ? null : bulkReader.getById(bulkId)); } private void setPosition(final ScheduleEntry entry, final int newPosition) { if (newPosition == entry.getPosition()) { return; } final int min = min(entry.getPosition(), newPosition); final int max = max(entry.getPosition(), newPosition); final int diff = signum(entry.getPosition() - newPosition); for (final ScheduleEntry e : entry.getSchedule().getEntries()) { if (e.getPosition() >= min && e.getPosition() <= max) { e.setPosition(e.getPosition() + diff); } } entry.setPosition(newPosition); } }