package org.academiadecodigo.bootcamp.fxlogin.service.user;

import org.academiadecodigo.bootcamp.fxlogin.model.User;
import org.academiadecodigo.bootcamp.fxlogin.utils.JpaUtils;
import org.academiadecodigo.bootcamp.fxlogin.utils.Security;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.NoResultException;
import javax.persistence.Persistence;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import java.util.List;

/**
 * MIT License
 * (c) 2017 Ricardo Constantino
 */

public class JpaUserService implements UserService {
    private EntityManagerFactory emf;

    public JpaUserService(EntityManagerFactory emf) {
        this.emf = emf;
    }

    public JpaUserService() {
        this.emf = Persistence.createEntityManagerFactory("test");
    }

    @Override
    public boolean authenticate(String username, String password) {
        User fetched = findByName(username);

        return fetched != null && fetched.getPassword().
                equals(Security.getHashed(password));
    }

    @Override
    public void addUser(User user) {
        JpaUtils<User> bootcampJpaUtils = new JpaUtils<>(emf);
        if (findByName(user.getUsername()) != null) {
            return;
        }
        bootcampJpaUtils.save(user);

    }

    @Override
    public User findByName(String username) {
        EntityManager em = emf.createEntityManager();

        try {
            CriteriaBuilder builder = em.getCriteriaBuilder();

            CriteriaQuery<User> criteriaQuery = builder.createQuery(User.class);

            Root<User> userRoot = criteriaQuery.from(User.class);

            criteriaQuery.select(userRoot);

            criteriaQuery.where(builder.equal(userRoot.get("username"), username));

            return em.createQuery(criteriaQuery).getSingleResult();
        } catch (NoResultException e) {
            return null;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    @Override
    public Long count() {
        EntityManager em = emf.createEntityManager();

        try {
            CriteriaBuilder builder = em.getCriteriaBuilder();

            CriteriaQuery<User> criteriaQuery = builder.createQuery(User.class);

            Root<User> userRoot = criteriaQuery.from(User.class);

            criteriaQuery.select(userRoot);

            List<User> fetched = em.createQuery(criteriaQuery).getResultList();

            return (long) fetched.size();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }
}
