/**
 * 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
 */
/*
 * Image.java
 * Last modified by: $Author: amarkhel $
 * $Revision: 13250 $	$Date: 2009-03-27 13:34:20 +0200 (Fri, 27 Mar 2009) $
 */
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.ManyToOne;
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.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Role;

@NamedQueries({
    @NamedQuery(
            name = "image-camera",
            query = "select distinct i.cameraModel from Image i"
    )
        }
)
/**
 * Class for representing Image Entity
 *  EJB3 Entity Bean
 *
 * @author Andrey Markhel
 */

@Entity
@Name("image")
@Table(name = "Images")
@Role(name = "selectedImage", scope = ScopeType.CONVERSATION)
public class Image implements Serializable {

    private static final long serialVersionUID = -7042878411608396483L;

    @Id
    @GeneratedValue
    @Column(name = "IMAGE_ID")
    private Long id = null;

    @Column(length = 255, nullable = false)
    @NotNull
    @NotEmpty
    @Length(min = 3)
    private String name;
    @Transient
    //TODO nick - remove this
    private boolean covering;

    @Column(length = 1024, nullable = false)
    @NotNull
    @NotEmpty
    @Length(min = 3)
    private String path;

    @ManyToMany(cascade = CascadeType.ALL)
    @JoinTable(name = "IMAGES_METATAGS",
            joinColumns =
            @JoinColumn(name = "CI_IMAGE_ID",
                    referencedColumnName = "IMAGE_ID"),
            inverseJoinColumns =
            @JoinColumn(name = "CI_METATAG_ID",
                    referencedColumnName = "METATAG_ID"))
    protected List<MetaTag> imageTags = new ArrayList<MetaTag>();


    /*
     * Comma separated tag value
     * */
    @Transient
    private String meta = "";

    @Column(length = 255)
    private String cameraModel;

    private int height;

    //TODO nick - should be changed to int
    private double size;

    private int width;

    @Temporal(TemporalType.TIMESTAMP)
    private Date uploaded;

    @Column(length = 1024)
    @NotNull
    @NotEmpty
    @Length(min = 3)
    private String description;

    @Temporal(TemporalType.TIMESTAMP)
    private Date created;

    @OneToMany(mappedBy = "image", cascade = {CascadeType.ALL}, fetch = FetchType.LAZY)
    @org.hibernate.annotations.LazyCollection(org.hibernate.annotations.LazyCollectionOption.EXTRA)
    @org.hibernate.annotations.OrderBy(clause = "date asc")
    private List<Comment> comments = new ArrayList<Comment>();

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "IMG_ALBUM_ID", referencedColumnName = "ALBUM_ID")
    private Album album;

    @NotNull
    private boolean allowComments;

    // ********************** Accessor Methods ********************** //

    /**
     * Getter for property id
     *
     * @return id of image
     */
    public Long getId() {
        return id;
    }

    /**
     * Getter for property name
     *
     * @return name of image
     */
    public String getName() {
        return name;
    }

    /**
     * Setter for property name
     *
     * @param name - name of image
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * Getter for property description
     *
     * @return description of image
     */
    public String getDescription() {
        return description;
    }

    /**
     * Setter for property description
     *
     * @param description - description of image
     */
    public void setDescription(String description) {
        this.description = description;
    }

    public String getPath() {
        return path;
    }

    public void setPath(String path) {
        this.path = path;
    }

    public Date getCreated() {
        return created;
    }

    public void setCreated(Date created) {
        this.created = created;
    }

    public Album getAlbum() {
        return album;
    }

    public void setAlbum(Album album) {
        this.album = album;
    }

    //---------------------------Business methods

    public void addComment(Comment comment) {
        if (comment == null) {
            throw new IllegalArgumentException("Null comment!");
        }
        if (comment.getImage() != null && !this.equals(comment.getImage())) {
            comment.getImage().getComments().remove(comment);
        }
        comment.setImage(this);
        comments.add(comment);
    }

    public void removeComment(Comment comment) {
        if (comment == null) {
            throw new IllegalArgumentException("Null comment");
        }
        //TODO nick - check that comments belongs to "this" image
        if(comment.getImage().equals(this)){
        	comment.setImage(null);
            comments.remove(comment);
        }else{
        	throw new IllegalArgumentException("Comment not belongs to this image");
        }
    }

    public List<Comment> getComments() {
        return comments;
    }

    public List<MetaTag> getImageTags() {
        return imageTags;
    }

    public void setImageTags(List<MetaTag> imageTags) {
        this.imageTags = imageTags;
    }

    public String getMeta() {
        StringBuilder s = new StringBuilder();
        for (MetaTag tag : this.imageTags) {
            s.append(tag.getTag()).append(", ");
        }

		//TODO nick - changed by nick
		if (s.length() >= 2) {
			s.delete(s.length() - 2, s.length());
		}
		return s.toString();
    }

    public void setMeta(String meta) {
        this.meta = meta;
    }

    public String getMetaString() {
        return meta;
    }

    public String getCameraModel() {
        return cameraModel;
    }

    public void setCameraModel(String cameraModel) {
        this.cameraModel = cameraModel;
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public double getSize() {
        return size;
    }

    public void setSize(double size) {
        this.size = size;
    }

    public int getWidth() {
        return width;
    }

    public void setWidth(int width) {
        this.width = width;
    }

    public Date getUploaded() {
        return uploaded;
    }

    public void setUploaded(Date uploaded) {
        this.uploaded = uploaded;
    }

    public void addMetaTag(MetaTag metatag) {
        if (metatag == null) {
            throw new IllegalArgumentException("Null metatag!");
        }
        if (!imageTags.contains(metatag)) {
            metatag.addImage(this);
            imageTags.add(metatag);
        }
    }

    public void removeMetaTag(MetaTag metatag) {
        if (metatag == null) {
            throw new IllegalArgumentException("Null metatag!");
        }
        if (imageTags.contains(metatag)) {
            metatag.removeImage(this);
            imageTags.remove(metatag);
        }
    }

    /**
     * @return the allowComments
     */
    public boolean isAllowComments() {
        return allowComments;
    }

    /**
     * @param allowComments the allowComments to set
     */
    public void setAllowComments(boolean allowComments) {
        this.allowComments = allowComments;
    }

    public boolean isCovering() {
        return this.equals(this.getAlbum().getCoveringImage());
    }

    public void setCovering(boolean covering) {
        this.covering = covering;
    }

    public MetaTag getTagByName(String s) {
        for (MetaTag t : imageTags) {
            if (t.getTag().equals(s)) {
                return t;
            }
        }
        return null;
    }

    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Image image = (Image) o;

        if (id != null ? !id.equals(image.id) : image.id != null) return false;
        if (path != null ? !path.equals(image.path) : image.path != null) return false;

        return true;
    }

    public int hashCode() {
        int result;
        result = (id != null ? id.hashCode() : 0);
        result = 31 * result + (path != null ? path.hashCode() : 0);
        return result;
    }
}
