PlaceBean.java 10.6 KB
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package fi.insomnia.bortal.beans;

import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import fi.insomnia.bortal.enums.Permission;
import fi.insomnia.bortal.enums.RolePermission;
import fi.insomnia.bortal.exceptions.BortalCatchableException;
import fi.insomnia.bortal.exceptions.PermissionDeniedException;
import fi.insomnia.bortal.facade.GroupMembershipFacade;
import fi.insomnia.bortal.facade.PlaceFacade;
import fi.insomnia.bortal.facade.PlaceGroupFacade;
import fi.insomnia.bortal.model.EventMap;
import fi.insomnia.bortal.model.EventPk;
import fi.insomnia.bortal.model.GroupMembership;
import fi.insomnia.bortal.model.LanEvent;
import fi.insomnia.bortal.model.Place;
import fi.insomnia.bortal.model.PlaceGroup;
import fi.insomnia.bortal.model.Product;
import fi.insomnia.bortal.model.User;

import javax.annotation.Resource;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.ejb.Timeout;
import javax.ejb.Timer;
import javax.ejb.TimerService;
import javax.persistence.RollbackException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 
 * @author tuukka
 */
@Stateless
public class PlaceBean implements PlaceBeanLocal {
    private static final String PLACE_RESERVE_TIMEOUTER = "Map reserve timeouter";
    private static final Logger logger = LoggerFactory.getLogger(PlaceBean.class);
    @EJB
    private GroupMembershipFacade gmemfacade;
    @Resource
    private TimerService ts;

    @EJB
    private PlaceFacade placeFacade;

    @EJB
    private PlaceGroupFacade pgfacade;
    @EJB
    private UserBeanLocal userbean;

    @EJB
    private ProductBeanLocal productBean;

    @EJB
    private EventBeanLocal eventBean;

    @EJB
    private PlaceGroupBeanLocal pgbean;

    @EJB
    private SecurityBeanLocal secubean;
    @EJB
    private EventMapBeanLocal mapfacade;

    @Override
    public Place mergeChanges(Place place) {
        userbean.fatalPermission(Permission.MAP, RolePermission.WRITE, "User tried to modify place ", place);
        return placeFacade.merge(place);
    }

    @Override
    public BigDecimal totalReservationPrice(EventMap e, Place newPlace) {

        Set<Place> places = new HashSet<Place>();
        places.addAll(placeFacade.findUsersReservations(e, userbean.getCurrentUser()));

        if (newPlace != null) {
            places.add(newPlace);
        }

        Map<Product, Integer> mockmap = getPlaceProductcount(places);

        BigDecimal total = BigDecimal.ZERO;

        for (Entry<Product, Integer> entry : mockmap.entrySet()) {
            logger.debug("Adding to price {} of {}", entry.getValue(), entry.getKey().getName());
            if (entry.getKey() != null) {
                total = total.add(productBean.calculateTotal(entry.getKey(), new BigDecimal(entry.getValue())));
            }
        }
        return total;
    }

    private static Map<Product, Integer> getPlaceProductcount(Collection<Place> places) {
        HashMap<Product, Integer> mockmap = new HashMap<Product, Integer>();

        for (Place p : places) {
            if (p != null) {
                Product prod = p.getProduct();
                Integer val = mockmap.get(prod);
                if (val == null) {
                    val = 0;
                }
                mockmap.put(prod, ++val);
            }
        }

        return mockmap;

    }

    // TODO: Kantakysely tähän!
    @Override
    public Place findPlace(EventMap e, int x, int y) {
        for (Place place : e.getPlaces()) {
            if (place.isCoordinateInPlace(x, y)) {
                return place;
            }
        }
        return null;

    }

    @Override
    public boolean reservePlace(Place p, User user) {
        userbean.fatalPermission(Permission.MAP, RolePermission.EXECUTE, "User does not have rights to reserve ( and buy) a place");
        boolean ret = placeFacade.reservePlace(p, user);

        boolean foundTimeout = false;
        for (Timer t : ts.getTimers()) {
            if (t.getInfo().equals(PLACE_RESERVE_TIMEOUTER)) {
                foundTimeout = true;
            }
        }
        if (!foundTimeout) {
            logger.info("Place timeout calculator not started. Starting new.");
            ts.createTimer(new Date(), 1000 * 60, PLACE_RESERVE_TIMEOUTER);
        }
        return ret;
    }

    @Timeout
    public void checkTimedOutPlaces(Timer timer) {
        // logger.debug("Checking Timed out places at {}", new Date());
        placeFacade.timeoutPlaces();
    }

    @Override
    public void releaseUsersPlaces() {
        logger.debug("timeouting places");
        placeFacade.releasePlaces(userbean.getCurrentUser());
    }

    @Override
    public boolean releasePlace(Place place, User user) {
        return placeFacade.releasePlace(user, place);

    }

    @Override
    public boolean buySelectedPlaces(EventMap e) throws BortalCatchableException {
        userbean.fatalPermission(Permission.MAP, RolePermission.EXECUTE, "User does not have rights to reserve ( and buy) a place");
        LanEvent event = eventBean.getCurrentEvent();
        User user = userbean.getCurrentUser();

        List<Place> places = placeFacade.findUsersReservations(e, user);
        if (places.size() <= 0) {
            return false;
        }
        PlaceGroup pg = new PlaceGroup(event, Calendar.getInstance(), Calendar.getInstance(), true);
        pg.setCreator(user);
        pgfacade.create(pg);

        // PlaceGroup pg = pgbean.createPlaceGroup(user);
        BigDecimal totalprice = totalReservationPrice(e, null);
        BigDecimal balance = userbean.getCurrentUser().getAccountBalance();
        if (balance.compareTo(totalprice) < 0) {
            logger.debug("User {} Could not buy things because account balance is too low!", user);
            return false;
        }

        for (Place p : places) {
            if (!p.buy(pg)) {
                throw new BortalCatchableException("Error while buying places");
            }
            placeFacade.merge(p);
            GroupMembership membership = new GroupMembership(event, pg, p, gmemfacade.createInviteToken(event));
            pg.getMembers().add(membership);
        }

        for (Entry<Product, Integer> line : getPlaceProductcount(places).entrySet()) {
            productBean.createAccountEvent(line.getKey(), new BigDecimal(line.getValue()), user);
        }
        return true;
    }

    @Override
    public void lockPlaceProduct(User user, Product prod, BigDecimal quantity) {

        BigDecimal loop = BigDecimal.ZERO;
        LanEvent event = eventBean.getCurrentEvent();
        PlaceGroup pg = new PlaceGroup(event, Calendar.getInstance(), Calendar.getInstance(), true);
        pg.setCreator(user);

        for (Place p : prod.getPlaces()) {

            if (!p.isTaken()) {

                p.buy(pg);
                GroupMembership currgm = new GroupMembership(event, pg, p, gmemfacade.createInviteToken(event));
                placeFacade.merge(p);
                currgm.setPlaceGroup(pg);
                pg.getMembers().add(currgm);

                loop = loop.add(BigDecimal.ONE);
                if (quantity.equals(BigDecimal.ONE)) {
                    boolean gmassoc = false;
                    for (GroupMembership gm : user.getGroupMemberships()) {
                        if (gm.getId().getEventId().equals(event.getId())) {
                            gmassoc = true;
                            break;
                        }

                    }
                    if (!gmassoc) {
                        logger.debug("Group membership not found. Associating user {} to place {}", user.getNick(), currgm.getPlaceReservation().getName());
                        user.getGroupMemberships().add(currgm);
                        currgm.setUser(user);
                    }
                }
                if (loop.compareTo(quantity) >= 0) {
                    break;
                }
            }
        }
        user.getPlaceGroups().add(pg);

    }

    @Override
    public int setBuyable(EventMap map, String like, boolean b) {
        userbean.fatalPermission(Permission.MAP, RolePermission.WRITE, "User tried to change place buyable: " + like + " to " + b);
        return placeFacade.setBuyable(map, like, b);

    }

    @Override
    public Place find(EventPk id) {
        userbean.fatalPermission(Permission.MAP, RolePermission.READ, "error reading place ", id);
        return placeFacade.find(id);
    }

    @Override
    public void checkMemberships() {
        List<Place> all = placeFacade.findAll(eventBean.getCurrentEvent());
        for (Place p : all) {
            if (p.getGroup() != null && p.getPlaceReserver() == null) {
                LanEvent event = eventBean.getCurrentEvent();
                String token = gmemfacade.createInviteToken(event);

                GroupMembership gm = new GroupMembership(event, p.getGroup(), p, token);
                p.getGroup().getMembers().add(gm);
                p.setPlaceReserver(gm);

            }

        }

    }

    @Override
    public Place lockPlaces(User user, Place place) {
        if (place.isTaken()) {
            logger.warn("Place {} is already taken", place);
            throw new PermissionDeniedException(secubean, userbean.getCurrentUser(), "NO RIGHT");
        }

        userbean.fatalPermission(Permission.SHOP, RolePermission.EXECUTE, "User tried to lock place without SHOP:EXECUTE");
        LanEvent ev = eventBean.getCurrentEvent();
        PlaceGroup pg = new PlaceGroup(ev, Calendar.getInstance(), Calendar.getInstance(), true);
        pg.setCreator(user);

        user.getPlaceGroups().add(pg);

        place.reserve(user);
        place.buy(pg);

        GroupMembership newgm = new GroupMembership(ev, pg, place, gmemfacade.createInviteToken(ev));

        pg.getMembers().add(newgm);

        boolean foundGm = false;
        for (GroupMembership gm : user.getGroupMemberships()) {
            logger.debug("Checking users gm:s found: {}", gm);
            if (gm.getId().getEventId().equals(ev.getId())) {
                foundGm = true;
                break;
            }
        }
        logger.debug("Foundgm {}", foundGm);
        if (!foundGm) {
            logger.debug("Membership not found. associating");
            newgm.setUser(user);
            user.getGroupMemberships().add(newgm);

            userbean.mergeChanges(user);
        }
        pgfacade.create(pg);
        place = placeFacade.merge(place);

        return place;
    }
}