/*
 * 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 httpauthenticationmechanism.ApplicationConfig;
import java.io.Serializable;
//import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import javax.enterprise.context.RequestScoped;
import javax.enterprise.context.SessionScoped;
import javax.enterprise.inject.Produces;
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.Customer;
import org.apache.log4j.Logger;
import plate.wellmann.shop.persistence.MyUserGroups;
import plate.wellmann.shop.persistence.Salt;
import javax.security.enterprise.credential.Password;

/**
 *
 * @author Patrick
 */
@Named
@SessionScoped
public class CustomerManager implements Serializable{
    
    final static Logger logger = Logger.getLogger(CustomerManager.class);
    
    //private final Charset UTF8_CHARSET = Charset.forName("UTF-8");
    
    private Customer currentCostumer = Customer.nullCustomer;
    
    @Inject
    private PasswordManager passwordManager;
    
    @PersistenceContext(name = "MySQL-Wellmann")
    private EntityManager em;
    
    public String demo(){
        Salt salt = new Salt();
        Customer test = new Customer("user@test.de", Arrays.toString(passwordManager.hashPassword("test".toCharArray(), ("salz".getBytes()), 3072)), salt);
        test.setGroups(new MyUserGroups(test, MyUserGroups.Group.MANAGER));
        currentCostumer = test;
        
        return "/ressources/manager/welcome.xhtml";
    }
    
    @Transactional
    public void init(){
        //logger.info("Password to string; " + Arrays.toString(passwordString));
        Salt salt = new Salt();
        //byte[] password = passwordManager.hashPassword("user".toCharArray(), salt.getSalt(), salt.getInterations());
        Customer test = new Customer("user@test.de", Arrays.toString(passwordManager.hashPassword("test".toCharArray(), ("salz".getBytes()), 3072)), salt);
        test.setGroups(new MyUserGroups(test, MyUserGroups.Group.USER));
        em.persist(test);
//        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 != Customer.nullCustomer){
            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 != Customer.nullCustomer;
    }
    
    public void logout(){
        currentCostumer = Customer.nullCustomer;
    }
    
    @Transactional
    private boolean loadCostumer(String email){
        try {
            
            //Customer newCostumer = init();
            //em.persist(newCostumer);
            
            TypedQuery<Customer> query = em.createNamedQuery("Customer.findByEmail", Customer.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 == Customer.nullCustomer){
            logger.error("Nullcustomer 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<Customer> query = em.createNamedQuery("Customer.findByEmail", Customer.class);
        query.setParameter("email", email);
        try {
            Customer cost = query.getSingleResult();
            logger.warn("User: " + currentCostumer.getEmail() + "tried to register allready registered user: " + email);
            return false;
        } catch (NoResultException e) {
            String pass = new String (passwordManager.generateRandomPassword());
            Salt salt = new Salt();
            byte[] password = passwordManager.hashPassword(pass.toCharArray(), salt.getSalt(), salt.getInterations());
            Customer newCostumer = new Customer(email, "Monat2018!", 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 = new String(passwordManager.generateRandomPassword());
        Salt salt = new Salt();
        byte[] password = passwordManager.hashPassword(pass.toCharArray(), salt.getSalt(), salt.getInterations());
        Customer newCostumer = new Customer(email, pass, 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;
    }
    
    private char[] genPW(String pw){
        return (new Password("test").getValue());
    }
    
    /*private String genPW(String pw){
        Map<String, String> parameters= new HashMap<>();
        parameters.put("Pbkdf2PasswordHash.Iterations", "3072");
        parameters.put("Pbkdf2PasswordHash.Algorithm", "PBKDF2WithHmacSHA512");
        parameters.put("Pbkdf2PasswordHash.SaltSizeBytes", "64");
        passwordHash.initialize(parameters);
        return passwordHash.generate(pw.toCharArray());
    }*/
    //@Transactional
    private String extractDomain(String email){
        return email.substring(email.indexOf("@") + 1);
    }
    
    @Transactional
    public boolean changePassword(String passwordOld, String passwordNew){
        return false; 
        //return passwordManager.changePassword(currentCostumer, passwordNew, passwordOld);
    }
    
    public String resetPassword(){
        return null;
    }
    
    @Produces
    @RequestScoped
    public Customer activeCostumer(){
        return currentCostumer;
    }
}
