/**
 * License Agreement.
 *
 *  JBoss RichFaces - Ajax4jsf Component Library
 *
 * Copyright (C) 2007  Exadel, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1 as published by the Free Software Foundation.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
 */
package org.richfaces.realworld.domain;

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

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 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.Role;
import org.jboss.seam.annotations.Scope;

@NamedQueries({
    @NamedQuery(
        name = "user-login",
        query = "from User u where u.login = :username and u.password = :password"
   ),
   @NamedQuery(
        name = "user-exist",
        query = "from User u where u.login = :login"
   ),
   @NamedQuery(
        name = "user-availableUsers",
        query = "select u.login from User u where u.login like :login"
   ),
    @NamedQuery(
        name = "user-rootAlbums",
        query = "from Album a  WHERE a.owner.login=:login and a.parent is null"
   ),
   @NamedQuery(
	        name = "user-user",
	        query = "from User u where u.login = :login"
	   )
})

@Entity
@Scope(ScopeType.CONVERSATION)
@Name("user")
@Role(name="selectedUser", scope=ScopeType.CONVERSATION)
@Table(name = "Users")
public class User implements Serializable {
	
	private static final long serialVersionUID = 1L;
	
	@Id
	@GeneratedValue
	@Column(name = "USER_ID")
	private Long id = null;
	 
	@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, nullable = false)
    @NotNull
    @NotEmpty
    @Length(min=3)
	private String login;
	
	@Column(length = 255, nullable = false)
    @NotNull
    @NotEmpty
    @Length(min=3)
	private String password;
	
	@Transient
	private String confirmPassword;
	
	@ManyToMany(mappedBy = "sharedOwners")
    private List<Album> favoriteAlbums = new ArrayList<Album>();
	
	@ManyToMany(mappedBy = "sharedOwners")
    private List<Image> favoriteImages = new ArrayList<Image>();
	
	@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>();
	
	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 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;
	}
	
	//---------------------------Business methods
	
    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);
    }

    public void removeAlbum(Album album) {
        if (album == null) {
            throw new IllegalArgumentException("Null album");
        }  
        album.setOwner(null);
        childAlbums.remove(album);
    }
    
    public void removeFriend(User friend) {
        if (friend == null) {
            throw new IllegalArgumentException("Null friend");
        }  
        friends.remove(friend);
    }
    


	public String getConfirmPassword() {
		return confirmPassword;
	}

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

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

	public List<Album> getFavoriteAlbums() {
		return favoriteAlbums;
	}

	public void addFriend(User friend) {
		this.friends.add(friend);
	}


	public void removeFromFavoriteAlbums(Album album) {
		favoriteAlbums.remove(album);
	}

	public void addFavoriteAlbum(Album album) {
		if (album == null) {
            throw new IllegalArgumentException("Null album!");
        } 
		if(favoriteAlbums.contains(album)){
			return;
		}
		favoriteAlbums.add(album);
	}
	
	public void removeFromFavoriteImages(Image image) {
		favoriteImages.remove(image);
	}

	public void addFavoriteImage(Image image) {
		if (image == null) {
            throw new IllegalArgumentException("Null image!");
        } 
		if(favoriteAlbums.contains(image)){
			return;
		}
		favoriteImages.add(image);
	}

	public List<Image> getFavoriteImages() {
		return favoriteImages;
	}
}