package ru.yandex.qe.dispenser.domain;

import java.util.Objects;

import javax.annotation.ParametersAreNonnullByDefault;

import org.apache.commons.lang3.builder.CompareToBuilder;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import ru.yandex.qe.dispenser.api.v1.DiResourceGroup;
import ru.yandex.qe.dispenser.domain.index.NormalizedPrimaryKeyBase;
import ru.yandex.qe.dispenser.domain.util.ValidationUtils;

/**
 * Группа {@link Resource ресурсов}. Объединяет ресурсы {@link Service провайдера} по некоторому признаку.
 */
@ParametersAreNonnullByDefault
public class ResourceGroup extends NormalizedPrimaryKeyBase<ResourceGroup.Key> {
    @NotNull
    private final String name;

    @Nullable
    private final Integer priority;

    private ResourceGroup(final Builder builder) {
        super(builder.key);
        name = ValidationUtils.requireNonNull(builder.name, "No name!");
        priority = builder.priority;
        if (builder.id != null) {
            setId(builder.id);
        }
    }

    @NotNull
    public String getName() {
        return name;
    }

    @Nullable
    public Integer getPriority() {
        return priority;
    }

    public DiResourceGroup toView() {
        return DiResourceGroup.withKey(getKey().getPublicKey())
                .inService(getKey().getService().toView())
                .withName(name)
                .withPriority(priority)
                .build();
    }

    public static class Key implements Comparable<Key> {
        @NotNull
        private final String key;
        @NotNull
        private final Service service;

        public Key(final String key, final Service service) {
            this.key = key;
            this.service = service;
        }

        @NotNull
        public String getPublicKey() {
            return key;
        }

        @NotNull
        public Service getService() {
            return service;
        }

        @Override
        public int compareTo(@NotNull final ResourceGroup.Key key) {
            return new CompareToBuilder()
                    .append(getPublicKey(), key.getPublicKey())
                    .append(getService(), key.getService())
                    .build();
        }

        @Override
        public boolean equals(final Object o) {
            if (this == o) {
                return true;
            }
            if (o == null || getClass() != o.getClass()) {
                return false;
            }
            final Key key1 = (Key) o;
            return Objects.equals(key, key1.key) &&
                    Objects.equals(service, key1.service);
        }

        @Override
        public int hashCode() {
            return Objects.hash(key, service);
        }

    }

    public static class Builder {
        @NotNull
        private final Key key;
        @Nullable
        private String name;
        @Nullable
        private Long id;
        @Nullable
        private Integer priority;

        public Builder(final String key, final Service service) {
            this.key = new Key(key, service);
        }

        public Builder(final long id, final String key, final Service service) {
            this(key, service);
            this.id = id;
        }

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

        @NotNull
        public Builder priority(@Nullable final Integer priority) {
            this.priority = priority;
            return this;
        }

        public Builder(final ResourceGroup resourceGroup) {
            key = resourceGroup.getKey();
            name = resourceGroup.getName();
            id = resourceGroup.getId();
            priority = resourceGroup.getPriority();
        }

        public ResourceGroup build() {
            return new ResourceGroup(this);
        }
    }
}

