package vut.msa.helpers;

import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;
import org.hibernate.Query;
import vut.msa.pojos.User;

/**
 * Helper pre objekt User. Trieda poskytuje zakladne funkcie pre pracu s objektom
 * User (uzivatel systemy), ako su vytvorenie, zmazanie, ziskanie a podobne.
 *
 */
public class UsersHelper extends Helper{

    private User user;
    private static final Logger llog = Logger.getLogger(UsersHelper.class);

    public UsersHelper() {
        super();
        user = new User();
    }

    //PROPERTY: user
    public User getUser() { return user; }

    /**
     * Metoda sluzi na ziskanie uzivatela na zaklade zadaneho ID.
     *
     * @param id identifikator hladaneho uzivatela
     * @return uzivatel so zadanym ID
     */
    public User getUserById (int id){

        this.user = null;

        try {
            openSession();
            user = (User) session.load(User.class, new Integer(id).shortValue());

            if (user != null)
                session.load(User.class, user.getId());
        } catch (Exception ex) {
            endTransaction(session.getTransaction(), false);
            llog.error("Nie je mozne ziskat uzivatela so zadanym ID:" + id, ex);
        }

        return user;
    }

    /**
     * Metoda sluzi na ziskanie uzivatela na zaklade zadaneho uzivatelskeho mena.
     *
     * @param username uziv. meno hladaneho uzivatela
     * @return uzivatel so zadanym menom
     */
    public User getUserByUsername (String username){

        this.user = null;

        try {
            openSession();
            Query q =
                    session.createQuery("from User u where"
                    + " u.username='" + username + "'");
            user = (User) q.uniqueResult();

            if (user != null)
                session.load(User.class, user.getId());
        } catch (Exception ex) {
            endTransaction(session.getTransaction(), false);
            llog.error("Nie je mozne ziskat uzivatela so zadanym uziv. menom:" + username, ex);
        }

        return user;
    }

    /**
     * Metoda sluzi na ziskanie uzivatela na zaklade zadaneho uzivatelskeho mena.
     *
     * @param username uzivatelske meno hladaneho uzivatela
     * @return uzivatel so zadanym uzivatelskym menom
     */
    public User getUserByPassword(String password) {

        try {
            openSession();
            String encrypted  =
                    vut.msa.security.MessageHash.getInstance().encrypt(password);
            Query q =
                    session.createQuery("from User u where"
                    + " u.password='" + encrypted + "'");
            user = (User) q.uniqueResult();
            System.out.println("Result: " + encrypted);
            if (user != null)
                session.load(User.class, user.getId());
        } catch (Exception ex) {
            endTransaction(session.getTransaction(), false);
            llog.error("Nie je mozne ziskat uzivatela so zadanym heslom.", ex);
        } finally {
        }

        return user;
    }


    /**
     * Metoda sluzi na vlozenie noveho uzivatela do databazy.
     *
     * @param newUser uzivatel, ktory ma byt vlozeny do databazy
     * @return <b>true<b> ak sa vlozenie podarilo, <b>false<b> ak zlyhalo
     * @throws LoggedException ak uzivatel nepresiel testami
     */
    public boolean addNewUser(User newUser) {

        try {
            openSession();

            //Jedna sa o transietny objekt, preto treba volat persist
            newUser.setPassword(vut.msa.security.MessageHash.getInstance().encrypt(newUser.getPassword()));

            session.persist(newUser);
            endTransaction(session.getTransaction(), true);
            return true;

        } catch (Exception lex) {
            llog.error(lex.getMessage());
            return false;
        }
    }

    /**
     * Metoda sluzi na zmazanie uzivatela z databazy.
     *
     * @param userToRemove uzivatel, ktory ma byt zmazany
     * @return true, ak sa operacia podarila, false, ak sa nepodarila
     */
    public boolean removeUser(User userToRemove) {
        try {
            openSession();

            user = (User) session.get(User.class, user.getId());
            session.delete(user);
            endTransaction(session.getTransaction(), true);
            return true;

        } catch (Exception lex) {
            llog.error(lex.getMessage());
            return false;
        }
    }


    /**
     * Metoda sluzi na ziskanie zoznamu uzivatelov ulozenych v databaze.
     *
     * @return zoznam uzivatelov z databazy
     */
    public List<User> getUsersList() {

        List<User> users = new ArrayList();

        try {
            openSession();
            Query q =
                    session.createQuery("from User order by username");

            users = q.list();

            for (User u : users) {
                session.load(User.class, u.getId());
            }

        } catch (Exception ex) {
            endTransaction(session.getTransaction(), false);
            log.error("Nie je mozne ziskat zoznam uzivatelov z databazy.", ex);
        }

        return users;
    }

    /**
     * Metoda sluzi na nalogovanie uzivatela do systemu. V pripade, ze ma uzivatel
     * zadane spravne heslo, metoda vrati "login", co sluzi na navigaciu do hlavneho
     * menu. V opacnom pripade zobrazi prihlasovacie okno.
     *
     * @return retazec login alebo logout
     */
    public String doLogin() {
        return doLogin(user.getPassword());
    }

    /**
     * Metoda sluzi na nalogovanie uzivatela do systemu. V pripade, ze ma uzivatel
     * zadane spravne heslo, metoda vrati "login", co sluzi na navigaciu do hlavneho
     * menu. V opacnom pripade zobrazi prihlasovacie okno.
     *
     * @return retazec login alebo logout
     */
    public String doLogin(String password) {

        user = getUserByPassword(password);
        if (user == null) {
            user = new User();
            log.info("Uivatel neprihlaseny.");
            return "logout";
        } else {
            log.info("Uzivatel prihlaseny.");
            return "login";
        }
    }
}
