package ru.ulstu.paper.model;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.validator.constraints.NotEmpty;
import ru.ulstu.file.model.FileDataDto;
import ru.ulstu.deadline.model.Deadline;
import ru.ulstu.user.model.UserDto;

import javax.validation.constraints.Size;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import static ru.ulstu.core.util.StreamApiUtils.convert;

public class PaperDto {
    private final static int MAX_AUTHORS_LENGTH = 60;

    private Integer id;
    @NotEmpty
    @Size(min = 3, max = 254)
    private String title;
    private Paper.PaperStatus status;
    private Date createDate;
    private Date updateDate;
    @NotEmpty
    private List<Deadline> deadlines = new ArrayList<>();
    private String comment;
    private String url;
    private Boolean locked;
    private List<FileDataDto> files = new ArrayList<>();
    private Set<Integer> authorIds;
    private Set<UserDto> authors;
    private Integer filterAuthorId;

    public PaperDto() {
        deadlines.add(new Deadline());
    }

    @JsonCreator
    public PaperDto(@JsonProperty("id") Integer id,
                    @JsonProperty("title") String title,
                    @JsonProperty("status") Paper.PaperStatus status,
                    @JsonProperty("createDate") Date createDate,
                    @JsonProperty("updateDate") Date updateDate,
                    @JsonProperty("deadlines") List<Deadline> deadlines,
                    @JsonProperty("comment") String comment,
                    @JsonProperty("url") String url,
                    @JsonProperty("locked") Boolean locked,
                    @JsonProperty("files") List<FileDataDto> files,
                    @JsonProperty("authorIds") Set<Integer> authorIds,
                    @JsonProperty("authors") Set<UserDto> authors) {
        this.id = id;
        this.title = title;
        this.status = status;
        this.createDate = createDate;
        this.updateDate = updateDate;
        this.deadlines = deadlines;
        this.comment = comment;
        this.url = url;
        this.locked = locked;
        this.files = files;
        this.authors = authors;
    }

    public PaperDto(Paper paper) {
        this.id = paper.getId();
        this.title = paper.getTitle();
        this.status = paper.getStatus();
        this.createDate = paper.getCreateDate();
        this.updateDate = paper.getUpdateDate();
        this.deadlines = paper.getDeadlines();
        this.comment = paper.getComment();
        this.url = paper.getUrl();
        this.locked = paper.getLocked();
        this.files = convert(paper.getFiles(), FileDataDto::new);
        this.authorIds = convert(paper.getAuthors(), user -> user.getId());
        this.authors = convert(paper.getAuthors(), UserDto::new);
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public Paper.PaperStatus getStatus() {
        return status;
    }

    public void setStatus(Paper.PaperStatus status) {
        this.status = status;
    }

    public Date getCreateDate() {
        return createDate;
    }

    public void setCreateDate(Date createDate) {
        this.createDate = createDate;
    }

    public Date getUpdateDate() {
        return updateDate;
    }

    public void setUpdateDate(Date updateDate) {
        this.updateDate = updateDate;
    }

    public List<Deadline> getDeadlines() {
        return deadlines;
    }

    public void setDeadlines(List<Deadline> deadlines) {
        this.deadlines = deadlines;
    }

    public String getComment() {
        return comment;
    }

    public void setComment(String comment) {
        this.comment = comment;
    }

    public Boolean getLocked() {
        return locked;
    }

    public void setLocked(Boolean locked) {
        this.locked = locked;
    }

    public List<FileDataDto> getFiles() {
        return files;
    }

    public void setFiles(List<FileDataDto> files) {
        this.files = files;
    }

    public Set<UserDto> getAuthors() {
        return authors;
    }

    public void setAuthors(Set<UserDto> authors) {
        this.authors = authors;
    }

    public Set<Integer> getAuthorIds() {
        return authorIds;
    }

    public void setAuthorIds(Set<Integer> authorIds) {
        this.authorIds = authorIds;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getAuthorsString() {
        return StringUtils.abbreviate(authors
                .stream()
                .map(author -> author.getLastName())
                .collect(Collectors.joining(", ")), MAX_AUTHORS_LENGTH);
    }

    public Integer getFilterAuthorId() {
        return filterAuthorId;
    }

    public void setFilterAuthorId(Integer filterAuthorId) {
        this.filterAuthorId = filterAuthorId;
    }
}
