package ru.yandex.qe.dispenser.ws.base_resources.model;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;

import ru.yandex.qe.dispenser.api.v1.DiCampaign;
import ru.yandex.qe.dispenser.api.v1.DiSegment;
import ru.yandex.qe.dispenser.api.v1.DiService;

@JsonIgnoreProperties(ignoreUnknown = true)
@ApiModel("Page of base resource limits")
public final class BaseResourceLimitsPageDto {

    private final List<BaseResourceLimitDto> limits;
    private final Map<Long, BaseResourceDto> baseResources;
    private final Map<Long, BaseResourceTypeDto> baseResourceTypes;
    private final Map<Long, DiService> providers;
    private final Map<Long, DiCampaign> campaigns;
    private final Map<Long, DiSegment> segments;
    private final Long nextFrom;

    @JsonCreator
    public BaseResourceLimitsPageDto(@JsonProperty("limits") List<BaseResourceLimitDto> limits,
                                     @JsonProperty("baseResources") Map<Long, BaseResourceDto> baseResources,
                                     @JsonProperty("baseResourceTypes") Map<Long, BaseResourceTypeDto> baseResourceTypes,
                                     @JsonProperty("providers") Map<Long, DiService> providers,
                                     @JsonProperty("campaigns") Map<Long, DiCampaign> campaigns,
                                     @JsonProperty("segments") Map<Long, DiSegment> segments,
                                     @JsonProperty("nextFrom") Long nextFrom) {
        this.limits = limits;
        this.baseResources = baseResources;
        this.baseResourceTypes = baseResourceTypes;
        this.providers = providers;
        this.campaigns = campaigns;
        this.segments = segments;
        this.nextFrom = nextFrom;
    }

    @ApiModelProperty("Base resource limits list")
    public List<BaseResourceLimitDto> getLimits() {
        return limits;
    }

    @ApiModelProperty("Base resources referenced by limits, indexed by base resource id")
    @JsonInclude(JsonInclude.Include.NON_EMPTY)
    public Map<Long, BaseResourceDto> getBaseResources() {
        return baseResources;
    }

    @ApiModelProperty("Base resource types referenced by base resources, indexed by base resource type id")
    @JsonInclude(JsonInclude.Include.NON_EMPTY)
    public Map<Long, BaseResourceTypeDto> getBaseResourceTypes() {
        return baseResourceTypes;
    }

    @ApiModelProperty("Referenced providers, indexed by id")
    @JsonInclude(JsonInclude.Include.NON_EMPTY)
    public Map<Long, DiService> getProviders() {
        return providers;
    }

    @ApiModelProperty("Referenced campaigns, indexed by id")
    @JsonInclude(JsonInclude.Include.NON_EMPTY)
    public Map<Long, DiCampaign> getCampaigns() {
        return campaigns;
    }

    @ApiModelProperty("Referenced segments, indexed by id")
    @JsonInclude(JsonInclude.Include.NON_EMPTY)
    public Map<Long, DiSegment> getSegments() {
        return segments;
    }

    @ApiModelProperty("Id of the last base resource limit on the page, use it to load the next page")
    @JsonInclude(JsonInclude.Include.NON_EMPTY)
    public Optional<Long> getNextFrom() {
        return Optional.ofNullable(nextFrom);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        BaseResourceLimitsPageDto that = (BaseResourceLimitsPageDto) o;
        return Objects.equals(limits, that.limits) &&
                Objects.equals(baseResources, that.baseResources) &&
                Objects.equals(baseResourceTypes, that.baseResourceTypes) &&
                Objects.equals(providers, that.providers) &&
                Objects.equals(campaigns, that.campaigns) &&
                Objects.equals(segments, that.segments) &&
                Objects.equals(nextFrom, that.nextFrom);
    }

    @Override
    public int hashCode() {
        return Objects.hash(limits, baseResources, baseResourceTypes, providers, campaigns,
                segments, nextFrom);
    }

    @Override
    public String toString() {
        return "BaseResourceLimitsPageDto{" +
                "limits=" + limits +
                ", baseResources=" + baseResources +
                ", baseResourceTypes=" + baseResourceTypes +
                ", providers=" + providers +
                ", campaigns=" + campaigns +
                ", segments=" + segments +
                ", nextFrom=" + nextFrom +
                '}';
    }

}
