package org.richfaces.realworld.domain;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
import javax.persistence.Version;

import org.hibernate.validator.Length;
import org.hibernate.validator.NotEmpty;
import org.hibernate.validator.NotNull;
import org.hibernate.validator.Pattern;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;

/*@NamedQueries({
    @NamedQuery(
        name = "User-rootAlbums",
        query = "select a from Album a where a.parent is null and a.owner=:owner"
   )
})*/

@Entity
@Name("user")
@Scope(ScopeType.SESSION)
@Table(name = "Users")
public class User implements Serializable {
	
	
	private static final long serialVersionUID = 1L;
	
	@Id
	@GeneratedValue
	@Column(name = "USER_ID")
	private Long id = null;
	
	@Version
	@Column(name = "OBJ_VERSION")
	private int version = 0;
	 
	@Column(length = 255, nullable = false)
    @NotNull
	@NotEmpty
    @Length(min=3)
	private String firstName;
	
	@Column(length = 255, nullable = false)
    @NotNull
    @NotEmpty
    @Length(min=3)
	private String secondName;
	
	@Column(length = 255, nullable = false)
    @NotNull
    @NotEmpty
    @Pattern(regex=".+@.+\\.[a-z]+", message="Not valid e-mail")
	private String email;
	
	@Column(length = 255)
	private String avatarPath;
	
	@Column(length = 255, nullable = false)
    @NotNull
    @NotEmpty
    @Length(min=3)
	private String login;
	
	@Column(length = 255, nullable = false)
    @NotNull
    @NotEmpty
    @Length(min=3)
	private String password;
	
	@Transient
	@NotNull
    @NotEmpty
    @Length(min=3)
	private String confirmPassword;
	
	@ManyToMany(mappedBy = "sharedOwners")
    private List<Album> sharedAlbums = new ArrayList<Album>();
	
	@ManyToMany
    @JoinTable(
        name = "USER_FRIENDS",
        joinColumns =        @JoinColumn(name = "USER1_ID"),
        inverseJoinColumns = @JoinColumn(name = "USER2_ID")
    )
	private List<User> friends;
	
	@Temporal(TemporalType.TIMESTAMP)
	private Date birthDate;
	
	@OneToMany(mappedBy = "owner", cascade = { CascadeType.ALL }, fetch = FetchType.LAZY)
	    @org.hibernate.annotations.LazyCollection(org.hibernate.annotations.LazyCollectionOption.EXTRA)
	    @org.hibernate.annotations.OrderBy(clause = "NAME asc")
	    private List<Album> childAlbums = new ArrayList<Album>();
	
	//private Address address;

	/**
	 * No-arg constructor for JavaBean tools
	 */
    public User() {
    }

	public String getFirstName() {
		return firstName;
	}

	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	public String getSecondName() {
		return secondName;
	}

	public void setSecondName(String secondName) {
		this.secondName = secondName;
	}

	public String getEmail() {
		return email;
	}

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

	public String getAvatarPath() {
		return avatarPath;
	}

	public void setAvatarPath(String avatarPath) {
		this.avatarPath = avatarPath;
	}

	public String getLogin() {
		return login;
	}

	public void setLogin(String login) {
		this.login = login;
	}

	public String getPassword() {
		return password;
	}

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

	public Date getBirthDate() {
		return birthDate;
	}

	public void setBirthDate(Date birthDate) {
		this.birthDate = birthDate;
	}

	public Long getId() {
		return id;
	}

	public List<Album> getChildAlbums() {
		return childAlbums;
	}

	public void setChildAlbums(List<Album> childAlbums) {
		this.childAlbums = childAlbums;
	}
	
	//---------------------------Business methods
	
	/**
	 * This method add image to collection of images of current album
	 * 
	 * @param image - image to add
	 */
    public void addAlbum(Album album) {
        if (album == null) {
            throw new IllegalArgumentException("Null album!");
        } 
        if (album.getOwner() != null && !this.equals(album.getOwner())) {
        	album.getOwner().getChildAlbums().remove(album);
        }   
        album.setOwner(this);
        childAlbums.add(album);
    }

	/**
	 * This method remove image from collection of images of album
	 * 
	 * @param image - image to remove
	 */
    public void removeAlbum(Album album) {
        if (album == null) {
            throw new IllegalArgumentException("Null album");
        }  
        album.setOwner(null);
        childAlbums.remove(album);
    }

	public String getConfirmPassword() {
		return confirmPassword;
	}

	public void setConfirmPassword(String confirmPassword) {
		this.confirmPassword = confirmPassword;
	}

	public List<User> getFriends() {
		return friends;
	}

	public void setFriends(List<User> friends) {
		this.friends = friends;
	}

	public List<Album> getSharedAlbums() {
		return sharedAlbums;
	}

	public void setSharedAlbums(List<Album> sharedAlbums) {
		this.sharedAlbums = sharedAlbums;
	}
}