package tutorial.core.repositories.jpa;



import java.io.UnsupportedEncodingException;
import java.util.Date;
import org.springframework.stereotype.Repository;
import tutorial.core.models.entities.Account;
import tutorial.core.repositories.AccountRepo;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import java.util.List;
import java.util.Properties;

import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;



/**
 * 
 * @author Xavier
 */
@Repository
public class JpaAccountRepo implements AccountRepo {

    @PersistenceContext
    private EntityManager em;
    
    /**
     *
     */
    public final String mailAccount = "noreply.webapp.admn@gmail.com";

    /**
     *
     */
    public final int adminUserType = 3;

    /**
     * 
     */
    public final int tempUserUserType = 1;

    @Override
    public String getMailAccount() {
        return mailAccount;
    }

    @Override
    public int getAdminUserType() {
        return adminUserType;
    }

    @Override
    public int getTempUserUserType() {
        return tempUserUserType;
    }

    @Override
    public List<Account> findAllAccounts() {
        Query query = em.createQuery("SELECT a FROM Account a");
        return query.getResultList();
    }

    @Override
    public Account findAccount(Long id) {
        return em.find(Account.class, id);
    }

    @Override
    public Account findAccountByName(String name) {
        Query query = em.createQuery("SELECT a FROM Account a WHERE a.name= :name");
        query.setParameter("name", name);
        List<Account> accounts = query.getResultList();
        if(accounts.isEmpty()) {
            return null;
        } else {
            return accounts.get(0);
        }
    }
    
    @Override
    public Account findAccountByType(String name, int accountType) {
        Query query = em.createQuery("SELECT a FROM Account a WHERE a.name= :name AND a.accountType= :type");
        query.setParameter("name", name);
        query.setParameter("type", accountType);
        List<Account> accounts = query.getResultList();
        if(accounts.isEmpty()) {
            return null;
        } else {
            return accounts.get(0);
        }
    }

    @Override
    public Account createAccount(Account data) {
        //SENDS MAIL BEFORE CREATING ACCOUNT
        sendMail(data);
        data.setPassword(MD5(data.getPassword()));
        em.persist(data);
        return data;
    }
    @Override
    public String MD5(String md5) {
        try {
             java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");
             byte[] array = md.digest(md5.getBytes("UTF8"));
             StringBuilder sb = new StringBuilder();
             for (int i = 0; i < array.length; ++i) {
               sb.append(Integer.toHexString((array[i] & 0xFF) | 0x100).substring(1,3));
            }
             return sb.toString();
         } catch (java.security.NoSuchAlgorithmException e) {
         } catch (UnsupportedEncodingException ex) {
        }
         return null;
     }

    @Override
    public List<Account> findAllActivatedAccounts() {
        Query query = em.createQuery("SELECT a FROM Account a WHERE a.activated <= :now AND a.created <= :now AND (a.removed is NULL OR a.removed > :now)");
        Date now = new Date();
        query.setParameter("now", now);
        return query.getResultList();
    }

    @Override
    public Account findActivatedAccountByName(String name) {
        Query query = em.createQuery("SELECT a FROM Account a WHERE a.name = :name AND a.activated <= :now AND a.created <= :now AND (a.removed is NULL OR a.removed > :now)");
        query.setParameter("name", name);
        Date now = new Date();
        query.setParameter("now", now);
        List<Account> accounts = query.getResultList();
        if(accounts.isEmpty()) {
            return null;
        } else {
            return accounts.get(0);
        }
    }
    
    
    private void sendMail(Account accountData){
        final String username = mailAccount;
        final String password = "testpass1";
        
        Properties props = new Properties();
        props.put("mail.smtp.auth", "true");
        props.put("mail.smtp.starttls.enable", "true");
        props.put("mail.smtp.host", "smtp.gmail.com");
        props.put("mail.smtp.port", "587");

        Session session = Session.getInstance(props,
          new javax.mail.Authenticator() {
                @Override
                protected PasswordAuthentication getPasswordAuthentication() {
                        return new PasswordAuthentication(username, password);
                }
          });
        try {
                Message message = new MimeMessage(session);
                message.setFrom(new InternetAddress(username));
                message.setRecipients(Message.RecipientType.TO,
                        InternetAddress.parse(accountData.getName()));
                message.setSubject("Llave de acceso a la aplicación");
                message.setText("Usuario: "+accountData.getName()+"\nPassword: "+accountData.getPassword());
                Transport.send(message);
        } catch (MessagingException e) {
                throw new RuntimeException(e);
        }
    }
    

    @Override
    public void modifyPassword(String name, String password) {
        Query query = em.createQuery("UPDATE Account SET password = :password WHERE name = :name");
        query.setParameter("name", name);
        query.setParameter("password", password);
        query.executeUpdate();
    }
}
