/*
 * 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.useradmin.facade;

import hu.astrid.debgen.mail.service.SendEmailService;
import hu.astrid.debgen.server.startup.ApplicationParameters;
import hu.astrid.debgen.useradmin.service.UserAdminService;
import hu.astrid.debgen.useradmin.servlet.UserAdminServlet;
import hu.astrid.debgen.authentication.domain.DebGenUser;
import hu.astrid.debgen.localization.service.LocalizationService;
import hu.astrid.toucan.control.persistence.DatabaseServiceClass;
import java.util.HashMap;
import java.util.List;
import org.hibernate.Session;

/**
 * Handles the user administration operations.
 * @author inagy
 */
public class UserAdminFacade extends DatabaseServiceClass {

    /**
     * Loads a User with the specified id
     * @param id The id of the user which should be loaded
     * @return The loaded user object
     * @throws Exception When DB fails
     */
    public DebGenUser loadUser(Long id) throws Exception {
        Session session = null;
        try {
            session = this.startSession();
            session.beginTransaction();
            UserAdminService service = (UserAdminService) UserAdminService.getInstance(session);
            DebGenUser user = service.load(DebGenUser.class, id);
            session.getTransaction().commit();
            return user;
        } catch (Exception ex) {
            session.isOpen();
            session.getTransaction().rollback();
            throw ex;
        } finally {
            closeSession();
        }
    }

    /**
     * Lists all users with the specified order
     * @param orderBy The name of the ordering attribute to use an ascending order
     * @return All users
     * @throws Exception When DB fails
     */
    public List<DebGenUser> listUsers(String orderBy) throws Exception {
        Session session = null;
        try {
            session = this.startSession();
            session.beginTransaction();
            UserAdminService service = (UserAdminService) UserAdminService.getInstance(session);
            List list = service.list(DebGenUser.class, orderBy);
            session.getTransaction().commit();
            return list;
        } catch (Exception ex) {
            session.isOpen();
            session.getTransaction().rollback();
            throw ex;
        } finally {
            closeSession();
        }
    }

    /**
     * Update a users data to the DB
     * @param user The new user data
     * @return The updated user
     * @throws Exception When DB fails
     */
    public DebGenUser modifyUser(DebGenUser user) throws Exception {
        return this.saveOrUpdateUser(user, false, null);
    }

    /**
     * Saves a new User to the DB and sends a registration mail
     * @param user The user data
     * @param password The starting password
     * @return The saved user object
     * @throws Exception When something fails
     */
    public DebGenUser registerUser(DebGenUser user, String password) throws Exception {
        return this.saveOrUpdateUser(user, true, password);
    }

    /**
     * Changes the password of the user
     * @param user The user
     * @param newPassword The new PW
     * @param newPasswordRetry The new PW again
     * @throws Exception When something fails
     */
    public void changePassword(DebGenUser user, String newPassword, String newPasswordRetry) throws Exception {
        user.validate();
        Session session = null;
        try {
            session = this.startSession();
            session.beginTransaction();
            UserAdminService service = (UserAdminService) UserAdminService.getInstance(session);
            service.changePassword(user, newPassword, newPasswordRetry);
            session.getTransaction().commit();
        } catch (Exception ex) {
            session.isOpen();
            session.getTransaction().rollback();
            throw ex;
        } finally {
            closeSession();
        }
    }

    /**
     * Saves or updates the user, and sends ragistration mail if the user is new
     * @param user The user object
     * @param newUser The use is new
     * @param passwordIfNew The password of the user if the user is new
     * @return The refreshed object
     * @throws Exception When DB or sendmail fails
     */
    private DebGenUser saveOrUpdateUser(DebGenUser user, boolean newUser, String passwordIfNew) throws Exception {
        user.validate();
        Session session = null;
        try {
            session = this.startSession();
            session.beginTransaction();
            UserAdminService service = (UserAdminService) UserAdminService.getInstance(session);
            if (newUser) {
                user.setMustChangePass(true);
            }
            service.create(user);
           // user = service.refresh(user);
            if (newUser) {
                this.sendRegistrationEmail(user, passwordIfNew);
            }
            session.getTransaction().commit();
            return user;
        } catch (Exception ex) {
            session.isOpen();
            session.getTransaction().rollback();
            throw ex;
        } finally {
            closeSession();
        }
    }

    /**
     * Sends a registration e-mail
     * @param registeredUser The user data
     * @param password The password
     * @throws Exception When sendmail is not possible
     */
    private void sendRegistrationEmail(DebGenUser registeredUser, String password) throws Exception {
        try {
            String applicationName = new LocalizationService().getMessage(ApplicationParameters.getApplicationName(), registeredUser.getLanguageISOCode());
            HashMap<String, String> map = new HashMap<String, String>();
            map.put("subject", "[" + applicationName + new LocalizationService().getMessage("] - Regisztráció", registeredUser.getLanguageISOCode()));
            map.put("fullName", registeredUser.getFullName());
            map.put("userName", registeredUser.getUserName());
            map.put("email", registeredUser.getEmail());
            map.put("password", password);
            SendEmailService service = new SendEmailService();
            service.sendMail(UserAdminServlet.class.getResource("/hu/astrid/debgen/mail/template/"+registeredUser.getLanguageISOCode()+"/registration.html"),
                    map, registeredUser.getEmail());
        } catch (Exception ex) {
            throw ex;
        }
    }

    /**
     * Sets and updates the users active attribute
     * @param id The id of the user
     * @param activeUser The new value of the attribute
     * @throws Exception When DB fails
     */
    public void setActiveUser(Long id, boolean activeUser) throws Exception {
        Session session = null;
        try {
            session = this.startSession();
            session.beginTransaction();
            UserAdminService service = (UserAdminService) UserAdminService.getInstance(session);
            DebGenUser user = service.load(id);
            user.setActiveUser(activeUser);
            service.create(user);
            session.getTransaction().commit();
        } catch (Exception ex) {
            session.isOpen();
            session.getTransaction().rollback();
            throw ex;
        } finally {
            closeSession();
        }
    }

    /**
     * Deletes the user with this id
     * @param id The id of the user
     * @throws Exception When DB fails
     */
    public void deleteUser(Long id) throws Exception {
        Session session = null;
        try {
            session = this.startSession();
            session.beginTransaction();
            UserAdminService service = (UserAdminService) UserAdminService.getInstance(session);
            DebGenUser user = service.load(id);
            service.delete(user);
            session.getTransaction().commit();
        } catch (Exception ex) {
            session.isOpen();
            session.getTransaction().rollback();
            throw ex;
        } finally {
            closeSession();
        }
    }

    /**
     * Refreshes the user object
     * @param user The user object
     * @throws Exception When DB fails
     */
    public void refresh(DebGenUser user) throws Exception {
        Session session = null;
        try {
            session = this.startSession();
            session.beginTransaction();
            UserAdminService service = (UserAdminService) UserAdminService.getInstance(session);
            service.refresh(user);
            session.getTransaction().commit();
        } catch (Exception ex) {
            session.isOpen();
            session.getTransaction().rollback();
            throw ex;
        } finally {
            closeSession();
        }
    }
}
