package ru.yandex.dispenser.validation.client.model;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;

/**
 * Create quota request.
 *
 * @author Dmitriy Timashov <dm-tim@yandex-team.ru>
 */
@JsonIgnoreProperties(ignoreUnknown = true)
public final class CreateQuotaRequest {

    private final List<CreateChange> changes;
    private final String description;
    private final String comment;
    private final String calculations;
    private final List<String> chartLinks;
    private final String chartLinksAbsenceExplanation;
    private final Map<String, String> additionalProperties;
    private final Reason resourcePreorderReasonType;
    private final Long goalId;
    private final String summary;
    private final String projectKey;
    private final String sourceProjectKey;
    private final Type type;

    @JsonCreator
    @SuppressWarnings("ParameterNumber")
    public CreateQuotaRequest(
            @JsonProperty("changes") List<CreateChange> changes,
            @JsonProperty("description") String description,
            @JsonProperty("comment") String comment,
            @JsonProperty("calculations") String calculations,
            @JsonProperty("chartLinks") List<String> chartLinks,
            @JsonProperty("chartLinksAbsenceExplanation") String chartLinksAbsenceExplanation,
            @JsonProperty("additionalProperties") Map<String, String> additionalProperties,
            @JsonProperty("resourcePreorderReasonType") Reason resourcePreorderReasonType,
            @JsonProperty("goalId") Long goalId,
            @JsonProperty("summary") String summary,
            @JsonProperty("projectKey") String projectKey,
            @JsonProperty("sourceProjectKey") String sourceProjectKey,
            @JsonProperty("type") Type type) {
        this.changes = changes;
        this.description = description;
        this.comment = comment;
        this.calculations = calculations;
        this.chartLinks = chartLinks;
        this.chartLinksAbsenceExplanation = chartLinksAbsenceExplanation;
        this.additionalProperties = additionalProperties;
        this.resourcePreorderReasonType = resourcePreorderReasonType;
        this.goalId = goalId;
        this.summary = summary;
        this.projectKey = projectKey;
        this.sourceProjectKey = sourceProjectKey;
        this.type = type;
    }

    public static Builder builder() {
        return new Builder();
    }

    public static Builder builder(CreateQuotaRequest createQuotaRequest) {
        return new Builder(createQuotaRequest);
    }

    public List<CreateChange> getChanges() {
        return changes;
    }

    public String getDescription() {
        return description;
    }

    public String getComment() {
        return comment;
    }

    public String getCalculations() {
        return calculations;
    }

    public List<String> getChartLinks() {
        return chartLinks;
    }

    public String getChartLinksAbsenceExplanation() {
        return chartLinksAbsenceExplanation;
    }

    @JsonInclude(JsonInclude.Include.NON_EMPTY)
    public Map<String, String> getAdditionalProperties() {
        return additionalProperties;
    }

    public Reason getResourcePreorderReasonType() {
        return resourcePreorderReasonType;
    }

    public Long getGoalId() {
        return goalId;
    }

    public String getSummary() {
        return summary;
    }

    public String getProjectKey() {
        return projectKey;
    }

    public String getSourceProjectKey() {
        return sourceProjectKey;
    }

    public Type getType() {
        return type;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        CreateQuotaRequest that = (CreateQuotaRequest) o;
        return Objects.equals(changes, that.changes) &&
                Objects.equals(description, that.description) &&
                Objects.equals(comment, that.comment) &&
                Objects.equals(calculations, that.calculations) &&
                Objects.equals(chartLinks, that.chartLinks) &&
                Objects.equals(chartLinksAbsenceExplanation, that.chartLinksAbsenceExplanation) &&
                Objects.equals(additionalProperties, that.additionalProperties) &&
                resourcePreorderReasonType == that.resourcePreorderReasonType &&
                Objects.equals(goalId, that.goalId) &&
                Objects.equals(summary, that.summary) &&
                Objects.equals(projectKey, that.projectKey) &&
                Objects.equals(sourceProjectKey, that.sourceProjectKey) &&
                type == that.type;
    }

    @Override
    public int hashCode() {
        return Objects.hash(changes, description, comment, calculations, chartLinks, chartLinksAbsenceExplanation,
                additionalProperties, resourcePreorderReasonType, goalId, summary, projectKey, sourceProjectKey, type);
    }

    @Override
    public String toString() {
        return "CreateQuotaRequest{" +
                "changes=" + changes +
                ", description='" + description + '\'' +
                ", comment='" + comment + '\'' +
                ", calculations='" + calculations + '\'' +
                ", chartLinks=" + chartLinks +
                ", chartLinksAbsenceExplanation='" + chartLinksAbsenceExplanation + '\'' +
                ", additionalProperties=" + additionalProperties +
                ", resourcePreorderReasonType=" + resourcePreorderReasonType +
                ", goalId=" + goalId +
                ", summary='" + summary + '\'' +
                ", projectKey='" + projectKey + '\'' +
                ", sourceProjectKey='" + sourceProjectKey + '\'' +
                ", type=" + type +
                '}';
    }

    public static final class Builder {

        private final List<CreateChange> changes = new ArrayList<>();
        private final List<String> chartLinks = new ArrayList<>();
        private final Map<String, String> additionalProperties = new HashMap<>();
        private String description;
        private String comment;
        private String calculations;
        private String chartLinksAbsenceExplanation;
        private Reason resourcePreorderReasonType;
        private Long goalId;
        private String summary;
        private String projectKey;
        private String sourceProjectKey;
        private Type type;

        private Builder() {
        }

        private Builder(CreateQuotaRequest createQuotaRequest) {
            this.description = createQuotaRequest.description;
            this.comment = createQuotaRequest.comment;
            this.calculations = createQuotaRequest.calculations;
            this.chartLinksAbsenceExplanation = createQuotaRequest.chartLinksAbsenceExplanation;
            this.resourcePreorderReasonType = createQuotaRequest.resourcePreorderReasonType;
            this.goalId = createQuotaRequest.goalId;
            this.summary = createQuotaRequest.summary;
            this.projectKey = createQuotaRequest.projectKey;
            this.sourceProjectKey = createQuotaRequest.sourceProjectKey;
            this.type = createQuotaRequest.type;
            this.changes.addAll(createQuotaRequest.changes);
            this.chartLinks.addAll(createQuotaRequest.chartLinks);
            this.additionalProperties.putAll(createQuotaRequest.additionalProperties);
        }

        public Builder description(String description) {
            this.description = description;
            return this;
        }

        public Builder comment(String comment) {
            this.comment = comment;
            return this;
        }

        public Builder calculations(String calculations) {
            this.calculations = calculations;
            return this;
        }

        public Builder chartLinksAbsenceExplanation(String chartLinksAbsenceExplanation) {
            this.chartLinksAbsenceExplanation = chartLinksAbsenceExplanation;
            return this;
        }

        public Builder resourcePreorderReasonType(Reason resourcePreorderReasonType) {
            this.resourcePreorderReasonType = resourcePreorderReasonType;
            return this;
        }

        public Builder goalId(Long goalId) {
            this.goalId = goalId;
            return this;
        }

        public Builder summary(String summary) {
            this.summary = summary;
            return this;
        }

        public Builder projectKey(String projectKey) {
            this.projectKey = projectKey;
            return this;
        }

        public Builder sourceProjectKey(String sourceProjectKey) {
            this.sourceProjectKey = sourceProjectKey;
            return this;
        }

        public Builder type(Type type) {
            this.type = type;
            return this;
        }

        public Builder addChange(CreateChange change) {
            this.changes.add(change);
            return this;
        }

        public Builder addChanges(Collection<? extends CreateChange> changes) {
            this.changes.addAll(changes);
            return this;
        }

        public Builder addChanges(CreateChange... changes) {
            this.changes.addAll(Arrays.asList(changes));
            return this;
        }

        public Builder addChartLink(String chartLink) {
            this.chartLinks.add(chartLink);
            return this;
        }

        public Builder addChartLinks(Collection<? extends String> chartLinks) {
            this.chartLinks.addAll(chartLinks);
            return this;
        }

        public Builder addChartLinks(String... chartLinks) {
            this.chartLinks.addAll(Arrays.asList(chartLinks));
            return this;
        }

        public Builder putAdditionalProperty(String key, String value) {
            this.additionalProperties.put(key, value);
            return this;
        }

        public Builder putAdditionalProperties(Map<? extends String, ? extends String> additionalProperties) {
            this.additionalProperties.putAll(additionalProperties);
            return this;
        }

        public CreateQuotaRequest build() {
            return new CreateQuotaRequest(changes, description, comment, calculations, chartLinks,
                    chartLinksAbsenceExplanation, additionalProperties, resourcePreorderReasonType,
                    goalId, summary, projectKey, sourceProjectKey, type);
        }

    }

}
