package model.person;

import model.person.enums.Call;
import java.io.Serializable;
import java.util.AbstractSet;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.persistence.*;

import model.AbstractEntity;
import model.files.UserPicture;
import model.person.enums.UserGroup;

/**
 * Entity implementation class for Entity: User
 *
 */
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@NamedQueries({
    @NamedQuery(name = Person.FIND_BY_EMAIL,
            query = "SELECT p FROM Person p WHERE p.email = :email"),
    @NamedQuery(name = Person.FIND_BY_ID,
            query = "SELECT p FROM Person p WHERE p.id = :id"),
    @NamedQuery(name = Person.FIND_BY_TOKEN,
            query = "SELECT p FROM Person p inner join p.tokens t where t.tokenHash = :tokenHash and t.tokenType = :tokenType and t.expiration > :timestamp")
})
public class Person extends AbstractEntity implements Serializable {

    public static final String FIND_BY_EMAIL = "Person.findByEmail";
    public static final String FIND_BY_ID = "Person.findByID";
    public static final String FIND_BY_TOKEN = "Person.findByToken";

    private static final long serialVersionUID = 1L;

    @Column(name = "Email", unique = true, nullable = false)
    private String email;

    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "Password_ID", nullable = false, unique = true)
    private Password password;

    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "Salt_ID", nullable = false, unique = true)
    private Salt salt;

    @Enumerated(EnumType.STRING)
    @Column(name = "Anrede")
    private Call call;

    @OneToMany(mappedBy = "person", orphanRemoval = true, cascade = CascadeType.ALL)
    private List<Token> tokens;
    
    @ElementCollection(targetClass = UserGroup.class)
    @Enumerated(EnumType.STRING)
    @JoinTable(name = "UserGroups", joinColumns = @JoinColumn(name = "UserID"))
    @Column(name = "UserGroups", nullable = false)
    private Set<UserGroup> userGroups;

    @Column(nullable = true)
    private String telefon;
    
    @Column(nullable = true)
    private String mobile;
    
    @Column(nullable = true)
    private String fax;

    @Column(nullable = false)
    private String firstname;
    
    @Column(nullable = true)
    private String lastname;
    
    @Column(nullable = true)
    private String title;
    
    @Column(nullable = true)
    private boolean active;
    
    @OneToOne(optional = true, cascade = CascadeType.ALL)
    private UserPicture userPicture;

    public Person() {
        super();
        active = false;
    }

    public Person(String email, byte[] password, Salt salt, Set<UserGroup> usergroups) {
        this.email = email;
        this.tokens = new ArrayList<>();
        this.salt = salt;
        this.password = new Password(this, password);
        this.userGroups = usergroups;
    }

    public String getEmail() {
        return email;
    }

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

    public Password getPassword() {
        return password;
    }

    public void setPassword(Password password) {
        this.password = password;
    }

    public Salt getSalt() {
        return salt;
    }

    public void setSalt(Salt salt) {
        this.salt = salt;
    }

    public Call getCall() {
        return call;
    }

    public void setCall(Call call) {
        this.call = call;
    }

    public String getTelefon() {
        return telefon;
    }

    public void setTelefon(String telefon) {
        this.telefon = telefon;
    }

    public String getMobile() {
        return mobile;
    }

    public void setMobile(String mobile) {
        this.mobile = mobile;
    }

    public String getFax() {
        return fax;
    }

    public void setFax(String fax) {
        this.fax = fax;
    }

    public String getFirstname() {
        return firstname;
    }

    public void setFirstname(String firstname) {
        this.firstname = firstname;
    }

    public String getLastname() {
        return lastname;
    }

    public void setLastname(String lastname) {
        this.lastname = lastname;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public List<Token> getTokens() {
        return tokens;
    }

    public void setTokens(List<Token> tokens) {
        this.tokens = tokens;
    }

    public void addToken(Token token) {
        if (this.tokens == null) {
            tokens = new ArrayList<>();
        }

        tokens.add(token);
    }

    public Set<UserGroup> getUserGroups() {
        return userGroups;
    }

    public void setUserGroups(Set<UserGroup> userGroups) {
        this.userGroups = userGroups;
    }
    
    public void addGroup(UserGroup userGroup){
        if (this.userGroups == null) {
            this.userGroups = new HashSet<>();
        }
        
        this.userGroups.add(userGroup);
    }

    public boolean isActive() {
        return active;
    }

    public void setActive(boolean active) {
        this.active = active;
    }

    public UserPicture getUserPicture() {
        return userPicture;
    }

    public void setUserPicture(UserPicture userPicture) {
        this.userPicture = userPicture;
    }
}
