package de.flower.rmt.service;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.Lists;
import com.mysema.query.types.Order;
import com.mysema.query.types.OrderSpecifier;
import com.mysema.query.types.Path;
import com.mysema.query.types.expr.BooleanExpression;
import de.flower.common.util.NameFinder;
import de.flower.rmt.model.db.entity.EventTeam;
import de.flower.rmt.model.db.entity.EventTeamPlayer;
import de.flower.rmt.model.db.entity.Invitation;
import de.flower.rmt.model.db.entity.Invitation_;
import de.flower.rmt.model.db.entity.QEventTeamPlayer;
import de.flower.rmt.model.db.entity.event.Event;
import de.flower.rmt.repository.IEventTeamPlayerRepo;
import de.flower.rmt.repository.IEventTeamRepo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
* @author flowerrrr
*/
@Service
@Transactional(readOnly = true, propagation = Propagation.REQUIRED)
public class EventTeamManager extends AbstractService implements IEventTeamManager {
@Autowired
private IEventTeamRepo eventTeamRepo;
@Autowired
private IEventTeamPlayerRepo eventTeamPlayerRepo;
@Autowired
private IInvitationManager invitationManager;
@Override
public List<EventTeam> findTeamsOrderByRank(final Event event) {
return eventTeamRepo.findByEventOrderByRankAsc(event);
}
@Override
public List<EventTeamPlayer> findEventTeamPlayers(final EventTeam eventTeam, final Path<?>... attributes) {
BooleanExpression isEventTeam = QEventTeamPlayer.eventTeamPlayer.eventTeam.eq(eventTeam);
List<EventTeamPlayer> items = eventTeamPlayerRepo.findAll(isEventTeam, new OrderSpecifier(Order.ASC, QEventTeamPlayer.eventTeamPlayer.order), attributes);
for (int i = 0; i < attributes.length; i++) {
if (attributes[i].equals(QEventTeamPlayer.eventTeamPlayer.invitation)) {
// load invitations with users as we need them later. fetching user name via attributes is not possible
// once loaded into session we avoid LIE
invitationManager.findAllByEvent(eventTeam.getEvent(), Invitation_.user);
}
}
return items;
}
@Override
public List<Invitation> findInvitationsInEventTeams(final Event event) {
BooleanExpression isEvent = QEventTeamPlayer.eventTeamPlayer.eventTeam.event.eq(event);
List<EventTeamPlayer> items = eventTeamPlayerRepo.findAll(isEvent, QEventTeamPlayer.eventTeamPlayer.invitation);
List<Invitation> invitations = Lists.transform(items, new Function<EventTeamPlayer, Invitation>() {
@Override
public Invitation apply(final EventTeamPlayer item) {
return item.getInvitation();
}
});
return invitations;
}
@Override
@Transactional(readOnly = false)
public EventTeam addTeam(final Event event) {
EventTeam entity = new EventTeam(event);
String name = NameFinder.newName("Team", "A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P".split("\\."), new Predicate<String>() {
@Override
public boolean apply(final String input) {
return eventTeamRepo.findByEventAndName(event, input) == null;
}
});
entity.setName(name);
// entity.setRank(0); // add at end of ranked teams
eventTeamRepo.save(entity);
return entity;
}
@Override
public List<EventTeam> findTeams(final Event event) {
return eventTeamRepo.findByEvent(event);
}
@Override
@Transactional(readOnly = false)
public void removeTeam(final EventTeam eventTeam) {
eventTeamRepo.delete(eventTeam);
}
@Override
@Transactional(readOnly = false)
public void addPlayer(final Long eventTeamId, final Long invitationId, final Long insertBeforePlayerId) {
EventTeam eventTeam = eventTeamRepo.findOne(eventTeamId);
Invitation invitation = invitationManager.loadById(invitationId);
// player already assigned to a team?
EventTeamPlayer player = eventTeamPlayerRepo.findByInvitation(invitation);
EventTeamPlayer insertBeforePlayer = null;
if (insertBeforePlayerId != null) {
insertBeforePlayer = eventTeamPlayerRepo.findOne(insertBeforePlayerId);
}
if (player != null) {
// is already player of given team
EventTeam oldTeam = player.getEventTeam();
if (oldTeam.equals(eventTeam)) {
if (player.equals(insertBeforePlayer)) {
// player dropped on itself - nothing to do
} else {
// resort player
eventTeam.removePlayer(player);
eventTeam.addPlayer(player, insertBeforePlayer);
eventTeamPlayerRepo.save(player);
eventTeamRepo.save(eventTeam);
}
} else {
// re-order oldTeam. close gap that player leaves when removed from the team
oldTeam.removePlayer(player);
// assign new team
player.setEventTeam(eventTeam);
// add to end of list
eventTeam.addPlayer(player, insertBeforePlayer);
eventTeamPlayerRepo.save(player);
eventTeamRepo.save(eventTeam);
}
} else {
EventTeamPlayer entity = new EventTeamPlayer(eventTeam, invitation);
eventTeam.addPlayer(entity, insertBeforePlayer);
eventTeamPlayerRepo.save(entity);
eventTeamRepo.save(eventTeam);
}
}
@Override
@Transactional(readOnly = false)
public void removePlayer(final Long playerId) {
EventTeamPlayer player = eventTeamPlayerRepo.findOne(playerId);
player.getEventTeam().removePlayer(player);
eventTeamRepo.save(player.getEventTeam());
eventTeamPlayerRepo.delete(playerId);
}
@Override
@Transactional(readOnly = false)
public void removeInvitation(final Long invitationId) {
Invitation invitation = invitationManager.loadById(invitationId);
EventTeamPlayer player = eventTeamPlayerRepo.findByInvitation(invitation);
if (player != null) {
removePlayer(player.getId());
}
}
@Override
public void save(final EventTeam eventTeam) {
validate(eventTeam);
eventTeamRepo.save(eventTeam);
}
@Override
@Transactional(readOnly = false)
public void setRank(final Long eventTeamId, final EventTeam insertBeforeEventTeam) {
EventTeam eventTeam = eventTeamRepo.findOne(eventTeamId);
// get all teams ordered by rank
List<EventTeam> teams = findTeamsOrderByRank(eventTeam.getEvent());
if (eventTeam.equals(insertBeforeEventTeam)) {
// dropped on itself -> do nothing
} else {
// remove team and then insert at specified position
teams.remove(eventTeam);
teams.add(teams.indexOf(insertBeforeEventTeam), eventTeam);
}
// now iterate of teams and set Rank according to index
for (EventTeam team : teams) {
team.setRank(teams.indexOf(team) + 1);
eventTeamRepo.save(team);
}
}
}