package com.qprogramming.tasq.events;
import com.qprogramming.tasq.account.Account;
import com.qprogramming.tasq.config.ResourceService;
import com.qprogramming.tasq.events.Event.Type;
import com.qprogramming.tasq.mail.MailMail;
import com.qprogramming.tasq.manage.AppService;
import com.qprogramming.tasq.projects.Project;
import com.qprogramming.tasq.support.Utils;
import com.qprogramming.tasq.task.watched.WatchedTask;
import com.qprogramming.tasq.task.watched.WatchedTaskService;
import com.qprogramming.tasq.task.worklog.LogType;
import com.qprogramming.tasq.task.worklog.WorkLog;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.core.io.Resource;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import java.io.StringWriter;
import java.util.*;
@Service
public class EventsService {
public static final String TASK = "task";
private static final String APPLICATION_NAME = "applicationName";
private static final String WL_MESSAGE = "wlMessage";
private static final String LOG_KEY = "log";
private static final String CUR_ACCOUNT = "curAccount";
private static final String EVENT_STR = "eventStr";
private static final String APPLICATION = "application";
private static final String ACCOUNT = "account";
private static final Logger LOG = LoggerFactory.getLogger(EventsService.class);
private static final String UTF_8 = "UTF-8";
private static final String EMAIL_TEMP_PATH = "email/";
private static final String MORE_DETAILS = "moreDetails";
private static final String TITLE = "title";
private EventsRepository eventsRepo;
private WatchedTaskService watchSrv;
private MailMail mailer;
private MessageSource msg;
private VelocityEngine velocityEngine;
private ResourceService resourceSrv;
private AppService appSrv;
private String applicationName;
@Autowired
public EventsService(EventsRepository eventsRepo, WatchedTaskService watchSrv, MailMail mailer, MessageSource msg,
VelocityEngine velocityEngine, ResourceService resourceSrv, AppService appSrv) {
this.watchSrv = watchSrv;
this.eventsRepo = eventsRepo;
this.mailer = mailer;
this.msg = msg;
this.velocityEngine = velocityEngine;
this.resourceSrv = resourceSrv;
this.appSrv = appSrv;
applicationName = appSrv.getProperty(AppService.APPLICATION_NAME);
}
public Event getById(Long id) {
return eventsRepo.findById(id);
}
/**
* Returns list of all events for currently logged account
*
* @return
*/
public List<Event> getEvents() {
List<Event> events = eventsRepo.findByAccountIdOrderByDateDesc(Utils.getCurrentAccount().getId());
return events != null ? events : new LinkedList<>();
}
/**
* Returns list of all events for task
*
* @return
*/
public List<Event> getTaskEvents(String task) {
List<Event> events = eventsRepo.findByTask(task);
return events != null ? events : new LinkedList<>();
}
/**
* Returns list of all events for currently logged account with Pageable
*
* @param page pageable object
* @return page with events
*/
public Page<Event> getEvents(Pageable page) {
return eventsRepo.findByAccountId(Utils.getCurrentAccount().getId(), page);
}
/**
* Returns list of all unread events for currently logged account
*
* @return list of all unread events
*/
public List<Event> getUnread() {
List<Event> unread = eventsRepo.findByAccountIdAndUnreadTrue(Utils.getCurrentAccount().getId());
return unread != null ? unread : new LinkedList<>();
}
/**
* Add event for each account that is watching task.
* Based on type, send e-mail if user selected to do so.
*
* @param log - worklog
* @param wlMessage additional worklog message ( can be empty )
* @param when - when event happened,
*/
public void addWatchEvent(WorkLog log, String wlMessage, Date when) {
String taskID = log.getTask().getId();
WatchedTask task = watchSrv.getByTask(taskID);
if (task != null) {
for (Account account : task.getWatchers()) {
if (!account.equals(Utils.getCurrentAccount())) {
Event event = new Event();
event.setTask(taskID);
event.setAccount(account);
event.setWho(log.getAccount().toString());
event.setUnread(true);
event.setLogtype((LogType) log.getType());
event.setDate(when);
event.setType(getEventType((LogType) log.getType()));
event.setMessage(wlMessage);
eventsRepo.save(event);
if (sendEmail(account, event.getType())) {
String baseUrl = appSrv.getProperty(AppService.URL);
Locale locale = new Locale(account.getLanguage());
String eventStr = msg.getMessage(((LogType) log.getType()).getCode(), null, locale);
StringBuilder subject = new StringBuilder("[");
subject.append(taskID);
subject.append("] ");
subject.append(task.getName());
String type = task.getType().getCode();
StringWriter stringWriter = new StringWriter();
VelocityContext context = new VelocityContext();
context.put(ACCOUNT, account);
context.put(APPLICATION, baseUrl);
context.put(APPLICATION_NAME, applicationName);
context.put(TASK, task);
context.put(WL_MESSAGE, wlMessage);
context.put(LOG_KEY, log);
context.put(CUR_ACCOUNT, Utils.getCurrentAccount());
context.put(EVENT_STR, eventStr);
velocityEngine.mergeTemplate(EMAIL_TEMP_PATH + account.getLanguage() + "/task.vm", UTF_8, context, stringWriter);
String message = stringWriter.toString();
LOG.info(account.getEmail());
LOG.info(subject.toString());
LOG.info(message);
Map<String, Resource> resources = resourceSrv.getBasicResourceMap();
resources.put(type, resourceSrv.getTaskTypeIcon(type));
resources.put("avatar", resourceSrv.getUserAvatar());
mailer.sendMail(MailMail.NOTIFICATION, account.getEmail(), subject.toString(), message,
resources);
resourceSrv.clean();
}
}
}
}
}
/**
* Add event related to project
*
* @param account user for which event will be added
* @param type type of event
* @param project project where event happened
*/
public void addProjectEvent(Account account, LogType type, Project project) {
Event event = new Event();
event.setAccount(account);
event.setWho(Utils.getCurrentAccount().toString());
event.setUnread(true);
event.setLogtype(type);
event.setDate(new Date());
event.setType(getEventType(type));
event.setMessage(project.toString());
eventsRepo.save(event);
if (sendEmail(account, event.getType())) {
String baseUrl = appSrv.getProperty(AppService.URL);
Locale locale = new Locale(account.getLanguage());
String eventStr = msg.getMessage(type.getCode(), null, locale);
String subject = msg.getMessage("event.newSystemEvent",
new Object[]{Utils.getCurrentAccount(), eventStr}, locale);
StringWriter stringWriter = new StringWriter();
VelocityContext context = new VelocityContext();
context.put(ACCOUNT, account);
context.put("type", type);
context.put(APPLICATION, baseUrl);
context.put(APPLICATION_NAME, applicationName);
context.put("project", project);
context.put(CUR_ACCOUNT, Utils.getCurrentAccount());
velocityEngine.mergeTemplate(EMAIL_TEMP_PATH + account.getLanguage() + "/project.vm", UTF_8, context, stringWriter);
String message = stringWriter.toString();
mailer.sendMail(MailMail.NOTIFICATION, account.getEmail(), subject, message,
resourceSrv.getBasicResourceMap());
}
}
/**
* Add system event with custom passed message and more info
*
* @param account account for which message will be sent
* @param type type of event
* @param message message ( will be sent as subject and event summary )
* @param moreDetails more detials message ( send as mail more info body )
*/
public void addSystemEvent(Account account, LogType type, String message, String moreDetails) {
Event event = new Event();
event.setAccount(account);
event.setWho(Utils.getCurrentAccount().toString());
event.setUnread(true);
event.setLogtype(type);
event.setDate(new Date());
event.setType(Type.SYSTEM);
event.setMessage(moreDetails);
eventsRepo.save(event);
if (sendEmail(account, event.getType())) {
String baseUrl = appSrv.getProperty(AppService.URL);
Locale locale = new Locale(account.getLanguage());
String subject = msg.getMessage("event.newSystemEvent",
new Object[]{Utils.getCurrentAccount(), message}, locale);
StringWriter stringWriter = new StringWriter();
VelocityContext context = new VelocityContext();
context.put(TITLE, subject);
context.put(ACCOUNT, account);
context.put(APPLICATION, baseUrl);
context.put(APPLICATION_NAME, applicationName);
context.put(CUR_ACCOUNT, Utils.getCurrentAccount());
context.put(MORE_DETAILS, moreDetails);
velocityEngine.mergeTemplate(EMAIL_TEMP_PATH + account.getLanguage() + "/other.vm", UTF_8, context, stringWriter);
String messageContent = stringWriter.toString();
mailer.sendMail(MailMail.NOTIFICATION, account.getEmail(), subject, messageContent,
resourceSrv.getBasicResourceMap());
}
}
/**
* Checks if user have e-mail notification enabled for passed type
*
* @param account - account checked for email settings
* @param type - type of event
* @return true if email should be send
*/
private boolean sendEmail(Account account, Type type) {
switch (type) {
case COMMENT:
return account.getCommentnotification();
case WATCH:
return account.getWatchnotification();
case SYSTEM:
return account.getSystemnotification();
default:
return false;
}
}
public void save(Event event) {
eventsRepo.save(event);
}
public void save(List<Event> events) {
eventsRepo.save(events);
}
public void delete(List<Event> events) {
eventsRepo.delete(events);
}
public void delete(Event event) {
eventsRepo.delete(event);
}
private Type getEventType(LogType type) {
switch (type) {
case ASSIGN_TO_PROJ:
return Type.SYSTEM;
case REMOVE_FROM_PROJ:
return Type.SYSTEM;
case COMMENT:
return Type.COMMENT;
default:
return Type.WATCH;
}
}
}