/*
 * This file is part of DebGen Biobank Software developed by ASTRID Research.
 * All rights reserved. Reproduction, modification, use or disclosure
 * to third parties without express authority is forbidden.
 *
 * Copyright ASTRID Research Inc., Hungary, 2009-2011.
 *
 * ASTRID Research
 * Headquaters: Csapo utca 42. Debrecen H-4029 HUNGARY
 * Phone: +36-52-533-173        Fax: +36-52-533-174
 * Web: http://www.astrid.hu    E-mail: info@astrid.hu
 *
 * Project name: DebGen Biobank Software project.
 * URLS:
 * Developers: Istvan Zoltan Nagy (istvan.nagy@astrid.hu)
 */
package hu.astrid.debgen.authentication.service;

import elements.Functions;
import hu.astrid.debgen.authentication.domain.DebGenUser;
import hu.astrid.debgen.authentication.exception.AuthenticationFailedException;
import hu.astrid.debgen.authentication.exception.InvalidPasswordException;
import hu.astrid.debgen.server.requestprocessor.exception.FormFillException;
import hu.astrid.shared.server.service.BaseOperationsAbstract;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;

import java.security.InvalidParameterException;
import java.util.Date;

/**
 * A Service to handle authentication related DB operations.
 * @author inagy
 */
public class AuthenticationService extends BaseOperationsAbstract {

    /**
     * Returns an instance of an AuthenticationService and sets its session.
     * @param session The session os the Service to use the DB connection.
     * @return A new instance.
     */
    public static BaseOperationsAbstract getInstance(Session session) {
        AuthenticationService AuthenticationService = new AuthenticationService();
        AuthenticationService.session = session;
        return AuthenticationService;
    }

    /**
     * Authenticates the user
     * @param userData The userData which should be checked
     * @return The user object if, the data is valid.
     * @throws AuthenticationFailedException When the data is not valid.
     * @throws Exception When some DB related error occurs.
     */
    public DebGenUser authenticate(DebGenUser userData) throws AuthenticationFailedException, Exception {
        if (userData == null) {
            throw new InvalidParameterException();
        }
        Criteria criteria = session.createCriteria(DebGenUser.class)
                .add(Restrictions.eq("userName", userData.getUserName()))
                .add(Restrictions.eq("hashedPassword", userData.getHashedPassword()));
        DebGenUser user = (DebGenUser) criteria.uniqueResult();
        if (user != null && user.isActiveUser()) {
            user.setLastLogin(new Date());
            session.update(user);
            return user;
        } else {
            throw new AuthenticationFailedException(userData);
        }
    }

    /**
     * Changes the password of the given user
     * @param userData The user
     * @param oldPassword The old password
     * @param newPassword The new password
     * @param newPasswordRetry The new password again
     * @throws FormFillException When the form is not filled properly.
     * @throws InvalidPasswordException When the password is invalid.
     * @throws AuthenticationFailedException When the authentication fails.
     * @throws Exception When some DB related error occurs.
     */
    public void changePassword(DebGenUser userData, String oldPassword, String newPassword, String newPasswordRetry, String newFullName, String newEmail)
            throws FormFillException, InvalidPasswordException, AuthenticationFailedException, Exception {

        if (newPassword.isEmpty() || newPasswordRetry.isEmpty()) {
            throw new FormFillException("A jelszó és a jelszó újra mezők kitöltése kötelező."); //i18
        }
        if (newPassword.equals(newPasswordRetry) == false) {
            throw new FormFillException("A két új jelszó mező tartalma nem egyező.");   //i18
        }
        DebGenUser.checkData(userData.getUserName(), newPassword, newFullName, newEmail);
        session.refresh(userData);
        if (!userData.getHashedPassword().equals(Functions.hashMD5(oldPassword))) {
            throw new FormFillException("A régi jelszó nem érvényes, kérem adja meg a helyes jelszót.");     //i18
        }
        userData.setHashedPassword(Functions.hashMD5(newPassword));
        userData.setFullName(newFullName);
        userData.setEmail(newEmail);
        userData.setMustChangePass(false);
        session.update(userData);
    }


}
