package ru.yandex.qe.dispenser.api.v1;

import java.io.IOException;
import java.util.Collections;
import java.util.Objects;
import java.util.Set;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import org.jetbrains.annotations.NotNull;

import ru.yandex.qe.dispenser.api.DtoBuilder;
import ru.yandex.qe.dispenser.api.util.JsonDeserializerBase;
import ru.yandex.qe.dispenser.api.util.SerializationUtils;

@JsonDeserialize(using = DiPermission.Deserializer.class)
public class DiPermission {

    @NotNull
    private final String login;
    private final Set<Permission> permissionSet;

    private DiPermission(final Builder builder) {
        this.login = builder.login;
        this.permissionSet = builder.permissionSet != null ? Collections.unmodifiableSet(builder.permissionSet) : null;

        Objects.requireNonNull(this.login, "Login is required!");
    }

    @NotNull
    public String getLogin() {
        return login;
    }

    public Set<Permission> getPermissionSet() {
        return permissionSet;
    }

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

    @Override
    public int hashCode() {
        return Objects.hash(login, permissionSet);
    }

    @Override
    public String toString() {
        return "DiPermission{" +
                "login='" + login + '\'' +
                ", permissionSet=" + permissionSet +
                '}';
    }

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

    public enum Permission {
        CAN_VIEW_PROVIDER_GROUP_REPORT,
        CAN_VIEW_OWNING_COST,
    }

    public static class Builder implements DtoBuilder<DiPermission> {
        private String login;
        private Set<Permission> permissionSet;

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

        public Builder permissionSet(final Set<Permission> permissionSet) {
            this.permissionSet = permissionSet;
            return this;
        }

        @NotNull
        @Override
        public DiPermission build() {
            return new DiPermission(this);
        }
    }

    static final class Deserializer extends JsonDeserializerBase<DiPermission> {

        private final static TypeReference<Set<Permission>> SET_TYPE_REFERENCE = new TypeReference<Set<Permission>>() {};

        @NotNull
        @Override
        public DiPermission deserialize(final @NotNull JsonParser jp, final @NotNull DeserializationContext dc) throws IOException {
            final JsonNode json = toJson(jp);


            return builder()
                    .login(json.get("login").asText())
                    .permissionSet(SerializationUtils.convertValue(json.get("permissionSet"), SET_TYPE_REFERENCE))
                    .build();
        }
    }
}
