package eu.dnetlib.server;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Service;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;

import eu.dnetlib.client.LoginService;
import eu.dnetlib.efg1914.authoring.managers.UserManager;
import eu.dnetlib.efg1914.authoring.managers.UserManagerException;
import eu.dnetlib.efg1914.authoring.users.User;
import eu.dnetlib.efg1914.commons.store.XMLStoreException;

/**
 * The server side implementation of the RPC service.
 */
@SuppressWarnings("serial")
@Service("LoginService")
public class LoginServiceImpl extends RemoteServiceServlet implements LoginService {
	private transient org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(LoginServiceImpl.class);

	// @Autowired
	private UserManager userManager;

	//
	private WebApplicationContext context;

	public LoginServiceImpl() {

	}

	public String login(String username, String password, boolean RememberMe) throws XMLStoreException {

		try {
			context = WebApplicationContextUtils.getWebApplicationContext(getServletContext());

			userManager = (UserManager) context.getBean("userManager");
			User u = userManager.login(username, password, RememberMe);

			if (u == null) {
				throw new XMLStoreException("user not authenticated");
			}

			Subject shiroSubject = userManager.get_subject(username);

			Session shiroSession = userManager.get_session(u);

			log.info("user  tokens " + shiroSubject.getPrincipals());
			// create session and store userid

			HttpServletRequest request = this.getThreadLocalRequest();
			HttpSession session = request.getSession(true);
			// session.setAttribute("UserID", 1);
			session.setAttribute("UserID", u);
			session.setAttribute("shiroSession", shiroSession);
			session.setAttribute("shiroSubject", shiroSubject);

			return session.getId();

		} catch (UserManagerException e) {
			e.printStackTrace();
			throw new XMLStoreException(e);

		}
	}

	@Deprecated
	public String login(User user, boolean RememberMe) throws XMLStoreException {
		HttpServletRequest request = this.getThreadLocalRequest();

		try {
			context = WebApplicationContextUtils.getWebApplicationContext(getServletContext());

			userManager = (UserManager) context.getBean("userManager");

			Subject shiroSubject = userManager.get_subject(user.getUsername());
			Session shiroSession = userManager.get_session(user);
			log.info("user  tokens " + shiroSubject.getPrincipals());

			HttpSession session = request.getSession(true);
			session.setAttribute("UserID", user);

			session.setAttribute("shiroSession", shiroSession);
			session.setAttribute("shiroSubject", shiroSubject);
			return session.getId();
		} catch (UserManagerException e) {
			throw new XMLStoreException(e);
			//
		}

		// create session and store userid

	}

	public boolean checkLogin() throws XMLStoreException {
		context = WebApplicationContextUtils.getWebApplicationContext(getServletContext());

		userManager = (UserManager) context.getBean("userManager");
		HttpServletRequest request = this.getThreadLocalRequest();
		// dont create a new one -> false
		HttpSession session = request.getSession(false);

		if (session == null || session.getAttribute("UserID") == null) {
			return false;
		}
		// return true;
		// log.info("user manager " + userManager.hashCode());
		Subject subj = (Subject) session.getAttribute("shiroSubject");
		if (subj != null && subj.isAuthenticated()) {
			return true;
		} else {
			return false;
		}

		// session and userid is available, looks like user is logged in.

	}

	public User getUser() {

		User user = null;
		HttpServletRequest httpServletRequest = this.getThreadLocalRequest();
		HttpSession session = httpServletRequest.getSession();
		Object userObj = session.getAttribute("UserID");
		if (userObj != null && userObj instanceof User) {
			user = (User) userObj;
		}
		return user;
	}

	public void logout() throws XMLStoreException {
		context = WebApplicationContextUtils.getWebApplicationContext(getServletContext());

		userManager = (UserManager) context.getBean("userManager");
		HttpServletRequest request = this.getThreadLocalRequest();
		// dont create a new one -> false
		HttpSession session = request.getSession(false);
		// Subject subj = (Subject) session.getAttribute("shiroSubject");
		// subj.logout();

		Object userObj = session.getAttribute("UserID");
		if (userObj != null && userObj instanceof User) {
			User user = (User) userObj;
			try {
				userManager.logout(user.getUsername(), user.getPassword());

			} catch (UserManagerException e) {
				throw new XMLStoreException(e);

			}
		}

		// do some logout stuff ...
		session.invalidate();

	}

}