/**
 * 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.GeneratedValue;
import javax.persistence.Id;
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.UniqueConstraint;

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.AutoCreate;
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.passwordHash = :password"
   ),
   @NamedQuery(
        name = "user-exist",
        query = "from User u where u.login = :login"
   ),
   @NamedQuery(
	        name = "user-user",
	        query = "from User u where u.login = :login"
	   )
})

@Entity
@Scope(ScopeType.CONVERSATION)
@Name("user")
@AutoCreate
@Role(name="selectedUser", scope=ScopeType.CONVERSATION)
@Table(name = "Users", uniqueConstraints = {
		@UniqueConstraint(columnNames = "login"),
		@UniqueConstraint(columnNames = "email")
		})
public class User implements Serializable {
	
	private static final long serialVersionUID = 1L;
	
	@Id
	@GeneratedValue
	@Column(name = "USER_ID")
	private Long id = null;
	
	@NotNull 
	private String passwordHash;
	
	@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
    //TODO nick - use e-mail validator
    @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;
	
	@Transient
	private String password;
	
	@Transient
	private String confirmPassword;
	
	@Temporal(TemporalType.TIMESTAMP)
	private Date birthDate;
	
	@NotNull
	private Sex sex;
	
	private Boolean hasAvatar;
	
	@OneToMany(mappedBy = "owner", cascade = { CascadeType.ALL})
    @org.hibernate.annotations.LazyCollection(org.hibernate.annotations.LazyCollectionOption.EXTRA)
    @org.hibernate.annotations.OrderBy(clause = "NAME asc")
    private List<Shelf> shelfs = new ArrayList<Shelf>();

	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 getPasswordHash() { return passwordHash; }
	public void setPasswordHash(String passwordHash) {
	this.passwordHash = passwordHash;
	}
	
	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;
	}
	
	//---------------------------Business methods
    
    public void addShelf(Shelf shelf) {
        if (shelf == null) {
            throw new IllegalArgumentException("Null shelf!");
        }    
        //TODO nick - remove shelf from the previous user?
        shelf.setOwner(this);
        shelfs.add(shelf);
    }

    public void removeShelf(Shelf shelf) {
        if (shelf == null) {
            throw new IllegalArgumentException("Null shelf");
        }  
        //TODO nick - check if owner is current user?
        if(shelf.getOwner().equals(this)){
        	shelf.setOwner(null);
            shelfs.remove(shelf);
        }else{
        	throw new IllegalArgumentException("Shelf not belonfs to this user!");
        }
    }

	public String getConfirmPassword() {
		return confirmPassword;
	}

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

	public List<Shelf> getShelfs() {
		return shelfs;
	}

	public void setShelfs(List<Shelf> shelfs) {
		this.shelfs = shelfs;
	}
	
	public int getCountShelfs() {
		return this.getShelfs() != null ? this.getShelfs().size() : 0;
	}

	public Sex getSex() {
		return sex;
	}

	public void setSex(Sex sex) {
		this.sex = sex;
	}

	public Boolean getHasAvatar() {
		return hasAvatar;
	}

	public void setHasAvatar(Boolean hasAvatar) {
		this.hasAvatar = hasAvatar;
	}
	
	public List<Album> getAllAlbums(){
		List<Album> albums = new ArrayList<Album>();
		for(Shelf s:getShelfs()){
			albums.addAll(s.getAlbums());
		}
		return albums;
	}
	
	public List<Image> getAllImages(){
		List<Image> images = new ArrayList<Image>();
		for(Shelf s:getShelfs()){
			for(Album a:s.getAlbums()){
				images.addAll(a.getImages());
			}
		}
		return images;
	}
}