/*
 * This file is part of DebGen Biobank Software developed by ASTRID Research.
 * All rights reserved. Reproduction, modification, use or disclosure
 * to third parties without express authority is forbidden.
 *
 * Copyright ASTRID Research Inc., Hungary, 2009-2011.
 *
 * ASTRID Research
 * Headquaters: Csapo utca 42. Debrecen H-4029 HUNGARY
 * Phone: +36-52-533-173        Fax: +36-52-533-174
 * Web: http://www.astrid.hu    E-mail: info@astrid.hu
 *
 * Project name: DebGen Biobank Software project.
 * URLS:
 * Developers: Istvan Zoltan Nagy (istvan.nagy@astrid.hu)
 */
package hu.astrid.debgen.authentication.domain;

import hu.astrid.debgen.authentication.exception.InvalidPasswordException;
import hu.astrid.debgen.exception.ValidationFailedException;
import hu.astrid.debgen.mail.service.EmailValidator;
import hu.astrid.toucan.control.bean.ToucanBean;
import hu.astrid.toucan.servlet.httprequesttoobjectparser.HttpRequestToObjectParser;
import java.io.Serializable;
import java.util.Date;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.servlet.http.HttpServletRequest;

/**
 * The Domain object of the Users
 * @author inagy
 */
@Entity
@Table(name = "debgen_users"/*, uniqueConstraints = {@UniqueConstraint(columnNames = {"userName", "email"})}*/)
public class DebGenUser implements ToucanBean, Serializable {

    private static final long serialVersionUID = 1L;
    private static final int MAX_PASS_LENGTH = 8;
    private static final int MIN_PASS_LENGTH = 6;
    private static final String PASSWORD_CHARSET = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String userName;
    private String email;
    private String hashedPassword;
    private String fullName;
    private boolean activeUser;
    private boolean userAdministrator;
    private boolean mustChangePass;
    @Temporal(javax.persistence.TemporalType.TIMESTAMP)
    private Date lastLogin;
    private boolean dataRecorder;
    private boolean researcher;
    protected String languageCode;

    /**
     * Get the value of languageCode
     *
     * @return the value of languageCode
     */
    public String getLanguageCode() {
        return languageCode;
    }

    /**
     * Set the value of languageCode
     *
     * @param languageCode new value of languageCode
     */
    public void setLanguageCode(String languageCode) {
        this.languageCode = languageCode;
    }

    /**
     * Get the value of researcher
     *
     * @return the value of researcher
     */
    public boolean isResearcher() {
        return researcher;
    }

    /**
     * Set the value of researcher
     *
     * @param researcher new value of researcher
     */
    public void setResearcher(boolean researcher) {
        this.researcher = researcher;
    }

    /**
     * Get the value of dataRecorder
     *
     * @return the value of dataRecorder
     */
    public boolean isDataRecorder() {
        return dataRecorder;
    }

    /**
     * Set the value of dataRecorder
     *
     * @param dataRecorder new value of dataRecorder
     */
    public void setDataRecorder(boolean dataRecorder) {
        this.dataRecorder = dataRecorder;
    }

    public DebGenUser() {
    }

    /**
     * Check the password of the user
     * @param userName The username
     * @param password The password
     * @throws InvalidPasswordException
     */
    public static void checkData(String userName, String password) throws InvalidPasswordException {
        if (password == null) {
            throw new InvalidPasswordException();
        }
        if (password.indexOf("123") >= 0 || password.length() < MIN_PASS_LENGTH || password.length() > MAX_PASS_LENGTH || password.indexOf(userName) >= 0) {
            throw new InvalidPasswordException();
        }
    }
    
    public static void checkData(String userName, String password, String fullName, String email) throws InvalidPasswordException, ValidationFailedException {
    	
    	checkData(userName, password);
  
        List<String> properties = new ArrayList<String>();
        
        if (fullName!=null && fullName.length()==0){
        	properties.add("TELJESNEV");
        }
        
        if (email!=null && email.length()==0) {
        	properties.add("EMAIL");
		}
        
        if (properties.size()!=0){
        	throw new ValidationFailedException(properties);
        }
    }

    public DebGenUser(String userName, String hash) {
        this.userName = userName;
        this.hashedPassword = hash;
    }

    public boolean isMustChangePass() {
        return mustChangePass;
    }

    public void setMustChangePass(boolean mustChangePass) {
        this.mustChangePass = mustChangePass;
    }

    public boolean isActiveUser() {
        return activeUser;
    }

    public void setActiveUser(boolean activeUser) {
        this.activeUser = activeUser;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public boolean isUserAdministrator() {
        return userAdministrator;
    }

    public void setUserAdministrator(boolean userAdministrator) {
        this.userAdministrator = userAdministrator;
    }

    public String getHashedPassword() {
        return hashedPassword;
    }

    public void setHashedPassword(String hashedPassword) {
        this.hashedPassword = hashedPassword;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Date getLastLogin() {
        return lastLogin;
    }

    public void setLastLogin(Date lastLogin) {
        this.lastLogin = lastLogin;
    }

    public String getFullName() {
        return fullName;
    }

    public void setFullName(String fullName) {
        this.fullName = fullName;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    /**
     * Validate the current users datas
     * @return True if the current user (this) is valid
     * @throws ValidationFailedException When the user is not valid
     */
    public boolean validate() throws ValidationFailedException {
        ArrayList<String> properties = new ArrayList<String>(5);
        if (!this.checkLength(this.userName, 5, 10)) {
            properties.add("FELHASZNÁLÓI_NÉV");
        }
        if (!this.checkLength(email, 5, 255) || !EmailValidator.isValid(email)) {
            properties.add("E-MAIL_CÍM");
        }
        if (!this.checkLength(fullName, 5, 255)) {
            properties.add("NÉV");
        }
        if (properties.isEmpty()) {
            return true;
        } else {
            throw new ValidationFailedException(properties);
        }
    }

    /**
     * Checks the length of a String
     * @param what The string
     * @param min The minimal length
     * @param max The maximum length
     * @return min &lt; length &lt; max
     */
    private boolean checkLength(String what, int min, int max) {
        return (!(what == null || what.length() < min || what.length() > max));
    }

    public void convert(HttpServletRequest request) throws Exception {
        HttpRequestToObjectParser parser = HttpRequestToObjectParser.getInstance(request);
        this.userAdministrator = false;
        this.researcher = false;
        this.dataRecorder = false;
        parser.parseRequest(DebGenUser.class, this);
    }

    /**
     * Generates a new password for the user at the registration
     * @return password The generated password
     */
    public static String generatePassword() {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < MAX_PASS_LENGTH; i++) {
            int random = (int) (Math.random() * DebGenUser.PASSWORD_CHARSET.length());
            sb.append(DebGenUser.PASSWORD_CHARSET.charAt(random));
        }
        return sb.toString();
    }

    public String getLanguageISOCode() {
        if (languageCode.equals("EN")) {
            return "eng";
        }
        if (languageCode.equals("HU")) {
            return "hun";
        }
        return "hun";
    }
}
