package com.dwalldorf.timetrack.backend.service;

import com.dwalldorf.timetrack.backend.event.UserAuthenticationEvent;
import com.dwalldorf.timetrack.backend.exception.InvalidInputException;
import com.dwalldorf.timetrack.model.UserModel;
import com.dwalldorf.timetrack.repository.dao.UserDao;
import com.dwalldorf.timetrack.repository.exception.BadPasswordException;
import com.dwalldorf.timetrack.repository.exception.UserNotFoundException;
import javax.inject.Inject;
import javax.servlet.http.HttpSession;
import org.joda.time.DateTime;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class UserService {

    private static final String SESSION_USER_ATTRIBUTE = "user";

    private final UserDao userDao;

    private final ApplicationEventPublisher eventPublisher;

    private final HttpSession httpSession;

    @Inject
    public UserService(UserDao userDao, ApplicationEventPublisher eventPublisher, HttpSession httpSession) {
        this.userDao = userDao;
        this.eventPublisher = eventPublisher;
        this.httpSession = httpSession;
    }

    @Transactional
    public UserModel register(UserModel user) {
        final String username = user.getUsername();

        UserModel userModel = userDao.findByUsername(username);
        if (userModel != null) {
            final String message = "username or email already in use";

            eventPublisher.publishEvent(UserAuthenticationEvent.registrationFailedEvent(username, message));
            throw new InvalidInputException(message);
        }

        user.setRegistration(new DateTime());
        user = userDao.register(user);

        eventPublisher.publishEvent(UserAuthenticationEvent.registrationSuccessEvent(user));
        return user;
    }

    @Transactional
    public UserModel login(final String username, final String password) {
        final UserModel currentUser = getCurrentUser();

        if (currentUser != null) {
            final String currentUserUsername = currentUser.getUsername();
            if (!currentUserUsername.equals(username)) {
                eventPublisher.publishEvent(UserAuthenticationEvent.loginFailedEvent(
                        currentUserUsername,
                        String.format("user already logged in but tried to login as another user: '%s'", username))
                );
            } else {
                eventPublisher.publishEvent(UserAuthenticationEvent
                        .loginFailedEvent(currentUserUsername, "user already logged in")
                );
            }
            return currentUser;
        }

        try {
            UserModel loginUser = userDao.login(username, password);
            initializeUserSession(loginUser);
            return loginUser;
        } catch (UserNotFoundException ex) {
            eventPublisher.publishEvent(UserAuthenticationEvent.loginFailedEvent(username, "username not found"));
        } catch (BadPasswordException ex) {
            eventPublisher.publishEvent(UserAuthenticationEvent.loginFailedEvent(username, "wrong password"));
        }
        return null;
    }

    public void logout() {
        httpSession.invalidate();
        eventPublisher.publishEvent(UserAuthenticationEvent.logoutEvent(getCurrentUser()));
    }

    private void initializeUserSession(UserModel user) {
        httpSession.setAttribute(SESSION_USER_ATTRIBUTE, user);
        eventPublisher.publishEvent(UserAuthenticationEvent.loginSuccessEvent(user));
    }

    public UserModel getCurrentUser() {
        return (UserModel) httpSession.getAttribute(SESSION_USER_ATTRIBUTE);
    }
}
@@ -2802,37 +2802,127 @@
         
-initializeUserSession
+updateUserSession(loginUser);%0A            eventPublisher.publishEvent(UserAuthenticationEvent.loginSuccessEvent
 (loginUs
@@ -2916,32 +2916,33 @@
 Event(loginUser)
+)
 ;%0A            re
@@ -3479,56 +3479,39 @@
    p
-rivate void initializeUserSession(UserModel u
+ublic UserModel getCurrentU
 ser
+(
 ) %7B%0A
@@ -3509,32 +3509,51 @@
 User() %7B%0A       
+ return (UserModel)
  httpSession.set
@@ -3549,17 +3549,17 @@
 Session.
-s
+g
 etAttrib
@@ -3588,176 +3588,229 @@
 BUTE
-, user
 );%0A    
+%7D%0A%0A
     
-eventPublisher.publishEvent(UserAuthenticationEvent.loginSuccessEvent
+public UserModel update(UserModel user) %7B%0A        user = userDao.update
 (user)
-)
 ;%0A    
-%7D%0A%0A
     
-public UserModel g
+updateUserSession(user);%0A%0A        r
 et
-C
 ur
-rentUser() %7B
+n user;
 %0A    
+%7D%0A%0A
     
-return (UserModel)
+private void updateUserSession(final UserModel user) %7B%0A       
  htt
@@ -3810,33 +3810,33 @@
     httpSession.
-g
+s
 etAttribute(SESS
@@ -3845,26 +3845,32 @@
 N_USER_ATTRIBUTE
+, user
 );%0A    %7D%0A%7D

update user