package models;

import models.resource.Resource;
import models.resource.ResourceConvertible;
import org.joda.time.Duration;
import play.data.validation.Constraints;
import play.db.ebean.Model;
import utils.JodaDateUtil;

import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.MappedSuperclass;
import javax.persistence.Transient;
import java.util.Comparator;
import java.util.Date;

/**
 * 이슈 혹은 게시글의, 댓글
 */
@MappedSuperclass
abstract public class Comment extends Model implements TimelineItem, ResourceConvertible {
    private static final long serialVersionUID = 1L;

    @Id
    public Long id;

    @Lob @Constraints.Required
    public String contents;

    @Constraints.Required
    public Date createdDate;

    public Long authorId;
    public String authorLoginId;
    public String authorName;

    /**
     * <p>댓글을 생성한다.</p>
     */
    public Comment() {
        createdDate = new Date();
    }

    /**
     * <p>몇일 전에 작성되었는지 반환한다.</p>
     *
     * @return 몇일 전에 작성되었는지
     */
    public Duration ago() {
        return JodaDateUtil.ago(this.createdDate);
    }

    /**
     * <p>이 댓글을 리소스 형식으로 반환한다.</p>
     *
     * <p>when: 이 리소스에 대해,
     * <ul>
     *     <li>접근권한이 있는지 검사할 때</li>
     *     <li>첨부파일을 첨부하거나 가져올 때</li>
     * </ul>
     * </p>
     *
     * @return {@link Resource}로서의 댓글
     */
    @Override
    abstract public Resource asResource();

    /**
     * <p>이 댓글을 가지고 있는 이슈 혹은 게시글을 반환한다.</p>
     *
     * @return 이 댓글을 가지고 있는 이슈 혹은 게시글
     */
    abstract public AbstractPosting getParent();

    /**
     * <p>이 댓글을 작성한 저자를 설정한다.</p>
     *
     * <p>저자의 아이디, 로그인 아이디, 이름을 이 댓글에 저장해둔다. 아이디만 저장하지 않는 이유는, 저자가 탈퇴하여
     * 그 사용자에 대한 정보가 시스템에서 사라질 수도 있기 때문이다.</p>
     *
     * @param user 이 댓글을 작성한 저자
     */
    @Transient
    public void setAuthor(User user) {
        authorId = user.id;
        authorLoginId = user.loginId;
        authorName = user.name;
    }

    /**
     * <p>이 댓글을 저장한다.</p>
     *
     * <p>그 후 이 댓글을 갖고 게시글도 갱신한다.</p>
     */
    public void save() {
        super.save();
        getParent().update();
    }

    /**
     * <p>이 댓글을 삭제한다.</p>
     *
     * <p>동시에 모든 첨부파일을 삭제하고, 이 댓글을 갖고 게시글도 갱신한다.</p>
     */
    public void delete() {
        Attachment.deleteAll(asResource());
        NotificationEvent.deleteBy(this.asResource());
        super.delete();
        getParent().update();
    }

    public static Comparator<Comment> comparator(){
        return new Comparator<Comment>() {
            @Override
            public int compare(Comment o1, Comment o2) {
                return o1.createdDate.compareTo(o2.createdDate);
            }
        };
    }

    public Date getDate() {
        return createdDate;
    }
}

@@ -87,16 +87,128 @@
 rtible;%0A
+import org.apache.commons.lang3.builder.EqualsBuilder;%0Aimport org.apache.commons.lang3.builder.HashCodeBuilder;%0A
 import o
@@ -2837,10 +2837,1124 @@
 ;%0A    %7D%0A
+%0A%0A    @Override%0A    public boolean equals(Object obj) %7B%0A        if (obj == null) %7B%0A            return false;%0A        %7D%0A        if (obj == this) %7B%0A            return true;%0A        %7D%0A        if (obj.getClass() != getClass()) %7B%0A            return false;%0A        %7D%0A        Comment rhs = (Comment) obj;%0A        return new EqualsBuilder()%0A                .appendSuper(super.equals(obj))%0A                .append(this.id, rhs.id)%0A                .append(this.contents, rhs.contents)%0A                .append(this.createdDate, rhs.createdDate)%0A                .append(this.authorId, rhs.authorId)%0A                .append(this.authorLoginId, rhs.authorLoginId)%0A                .append(this.authorName, rhs.authorName)%0A                .isEquals();%0A    %7D%0A%0A    @Override%0A    public int hashCode() %7B%0A        return new HashCodeBuilder()%0A                .appendSuper(super.hashCode())%0A                .append(id)%0A                .append(contents)%0A                .append(createdDate)%0A                .append(authorId)%0A                .append(authorLoginId)%0A                .append(authorName)%0A                .toHashCode();%0A    %7D%0A
 %7D%0A

add equals implementation