/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package plate.wellmann.shop.business;

import java.io.Serializable;
import java.util.Arrays;
import javax.enterprise.context.SessionScoped;
import javax.inject.Inject;
import javax.inject.Named;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import javax.transaction.Transactional;
import plate.wellmann.shop.persistence.Costumer;
import org.apache.log4j.Logger;
import plate.wellmann.shop.persistence.Salt;

/**
 *
 * @author Patrick
 */
@Named
@SessionScoped
public class CostumerManager implements Serializable{
    
    final static Logger logger = Logger.getLogger(CostumerManager.class);
    
    private Costumer currentCostumer = Costumer.nullCostumer;
    
    @Inject
    private PasswordManager passwordManager;
    
    @PersistenceContext
    private EntityManager em;
    
    @Transactional
    private Costumer init(){
        Salt salt = new Salt();
        byte[] password = passwordManager.hashPassword("user".toCharArray(), salt.getSalt(), salt.getInterations());
        return new Costumer("user@test.de", password, salt);
//        try {
//            em.persist(testCostumer);
//            logger.debug("user@test.de got registered");
//        } catch (Exception e) {
//            logger.error("Init persisting doenst work : " + e.toString());
//        }
    }
    
    @Transactional
    public boolean login(String email, String password){
        if(currentCostumer != Costumer.nullCostumer){
            logout();
        }
        if (loadCostumer(email)) {
            byte[] pw = passwordManager.hashPassword(password.toCharArray(), currentCostumer.getSalt().getSalt(), currentCostumer.getSalt().getInterations());
            if(Arrays.equals(pw, currentCostumer.getPassword().getPassword())){
                logger.info("Passwordcheck correct " + email);
                for(int i = 0; i < pw.length; i++){
                    pw[i] = 0;
                }
                return true;
            }
        }
        return false;
    }
    
    public boolean isLoggedIn() {
        return currentCostumer != Costumer.nullCostumer;
    }
    
    public void logout(){
        currentCostumer = Costumer.nullCostumer;
    }
    
    @Transactional
    private boolean loadCostumer(String email){
        try {
            
            Costumer newCostumer = init();
            em.persist(newCostumer);
            
            TypedQuery<Costumer> query = em.createNamedQuery("Costumer.findByEmail", Costumer.class);
            query.setParameter("email", email);
            this.currentCostumer = query.getSingleResult();
            logger.info(email + " sucessfully loaded.");
            return true;
        } catch (Exception e) {
            if (logger.isDebugEnabled()) {
                logger.error(email + " couldn't be loaded. " + e.toString());
            }
            return false;
        }
    }
    
    /**
     * Function for register as Superuser 
     * 
     * TODO Check for Superuser
     * @param email
     * @return boolean if succesfull
     */
    @Transactional
    public boolean register(String email) {
        
        if(currentCostumer == Costumer.nullCostumer){
            logger.error("Nullcostumer tried to register user" + email);
            logout();
            return false;
        }
        //extract domain
        String domain = extractDomain(email);
        String userDomain = extractDomain(currentCostumer.getEmail());
        
        logger.info("trying to register User to " + domain + " by user: " + currentCostumer.getEmail());
        if(!userDomain.equals(domain)){
            logger.warn("Cannot register " + email + " to " + domain + " by " + currentCostumer.getEmail());
            return false;
        }
        
        TypedQuery<Costumer> query = em.createNamedQuery("Costumer.findByEmail", Costumer.class);
        query.setParameter("email", email);
        try {
            Costumer cost = query.getSingleResult();
            logger.warn("User: " + currentCostumer.getEmail() + "tried to register allready registered user: " + email);
            return false;
        } catch (NoResultException e) {
            String pass = org.apache.commons.codec.binary.Base64.encodeBase64String(passwordManager.generateRandomPassword());
            Salt salt = new Salt();
            byte[] password = passwordManager.hashPassword(pass.toCharArray(), salt.getSalt(), salt.getInterations());
            Costumer newCostumer = new Costumer(email, password, salt, currentCostumer.getDomain());
            currentCostumer.getDomain().addCostumer(newCostumer);
            em.persist(newCostumer);
            logger.info("New Costumer was registered: " + email + " by " + currentCostumer.getEmail());
            return true;
        }
    }
    
    @Transactional
    public boolean registerNewCostumerDomain(String email){
        String pass = org.apache.commons.codec.binary.Base64.encodeBase64String(passwordManager.generateRandomPassword());
        Salt salt = new Salt();
        byte[] password = passwordManager.hashPassword(pass.toCharArray(), salt.getSalt(), salt.getInterations());
        Costumer newCostumer = new Costumer(email, password, salt);
        logger.info("User: " + currentCostumer.getEmail() + "trying to register user: " + email);
        try {
            em.persist(newCostumer);
        } catch (Exception e) {
            logger.error("User: " + currentCostumer.getEmail() + "tried to register user: " + email + " with: " + e.toString());
            return false;
        }
        return false;
    }
    //@Transactional
    private String extractDomain(String email){
        return email.substring(email.indexOf("@") + 1);
    }
    
    @Transactional
    public boolean changePassword(String passwordOld, String passwordNew){
         return passwordManager.changePassword(currentCostumer, passwordNew, passwordOld);
    }
    
    public String resetPassword(){
        return null;
    }
}
