package ru.ulstu.paper.model;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.hibernate.validator.constraints.NotEmpty;
import ru.ulstu.deadline.model.DeadlineDto;
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 Integer id;
    @NotEmpty
    @Size(min = 3, max = 100)
    private String title;
    private Paper.PaperStatus status;
    private Date createDate;
    private Date updateDate;
    @NotEmpty
    private List<DeadlineDto> deadlines = new ArrayList<>();
    private String comment;
    private Boolean locked;
    private String tmpFileName;
    private Integer fileId;
    private String fileName;
    private Date fileCreateDate;
    private Set<Integer> authorIds;
    private Set<UserDto> authors;

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

    @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<DeadlineDto> deadlines,
                    @JsonProperty("comment") String comment,
                    @JsonProperty("locked") Boolean locked,
                    @JsonProperty("tmpFileName") String tmpFileName,
                    @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.locked = locked;
        this.tmpFileName = tmpFileName;
        this.fileId = null;
        this.fileName = null;
        this.fileCreateDate = null;
        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 = convert(paper.getDeadlines(), DeadlineDto::new);
        this.comment = paper.getComment();
        this.locked = paper.getLocked();
        this.tmpFileName = null;
        this.fileId = paper.getFileData() == null ? null : paper.getFileData().getId();
        this.fileName = paper.getFileData() == null ? null : paper.getFileData().getName();
        this.fileCreateDate = paper.getFileData() == null ? null : paper.getFileData().getCreateDate();
        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<DeadlineDto> getDeadlines() {
        return deadlines;
    }

    public void setDeadlines(List<DeadlineDto> 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 String getTmpFileName() {
        return tmpFileName;
    }

    public void setTmpFileName(String tmpFileName) {
        this.tmpFileName = tmpFileName;
    }

    public Integer getFileId() {
        return fileId;
    }

    public void setFileId(Integer fileId) {
        this.fileId = fileId;
    }

    public String getFileName() {
        return fileName;
    }

    public void setFileName(String fileName) {
        this.fileName = fileName;
    }

    public Date getFileCreateDate() {
        return fileCreateDate;
    }

    public void setFileCreateDate(Date fileCreateDate) {
        this.fileCreateDate = fileCreateDate;
    }

    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 getAuthorsString() {
        return authors
                .stream()
                .map(author -> author.getLastName())
                .collect(Collectors.joining(", "));
    }
}