package ru.yandex.qe.dispenser.domain.base_resources;

import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

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

@JsonIgnoreProperties(ignoreUnknown = true)
public final class BaseResourceChangeByService {

    private final Set<ServiceBaseResourceChange> changes;
    private final Map<Long, ServiceBaseResourceChange> changesByService;

    @JsonCreator
    public BaseResourceChangeByService(@JsonProperty("changes") Set<ServiceBaseResourceChange> changes) {
        this.changes = changes;
        this.changesByService = changes.stream()
                .collect(Collectors.toMap(ServiceBaseResourceChange::getServiceId, Function.identity()));
    }

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

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

    public Set<ServiceBaseResourceChange> getChanges() {
        return changes;
    }

    @JsonIgnore
    public Map<Long, ServiceBaseResourceChange> getChangesByService() {
        return changesByService;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        BaseResourceChangeByService that = (BaseResourceChangeByService) o;
        return Objects.equals(changes, that.changes) &&
                Objects.equals(changesByService, that.changesByService);
    }

    @Override
    public int hashCode() {
        return Objects.hash(changes, changesByService);
    }

    @Override
    public String toString() {
        return "BaseResourceChangeByService{" +
                "changes=" + changes +
                ", changesByService=" + changesByService +
                '}';
    }

    public static final class Builder {

        private final Set<ServiceBaseResourceChange> changes = new HashSet<>();

        private Builder() {
        }

        private Builder(BaseResourceChangeByService value) {
            this.changes.addAll(value.changes != null ? value.changes : Set.of());
        }

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

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

        public Builder addChanges(ServiceBaseResourceChange... changes) {
            this.changes.addAll(List.of(changes));
            return this;
        }

        public BaseResourceChangeByService build() {
            return new BaseResourceChangeByService(changes);
        }

    }

}
