package com.atlassian.bitbucket.mesh.auth;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.security.PublicKey;
import java.time.Duration;

import static java.util.Objects.requireNonNull;

public class ExpirablePublicKey {

    private final Duration expiryInterval;
    private final PublicKey publicKey;

    private ExpirablePublicKey(Builder builder) {
        expiryInterval = builder.expiryInterval;
        publicKey = builder.publicKey;
    }

    private ExpirablePublicKey(PublicKey publicKey) {
        this.publicKey = requireNonNull(publicKey, "publicKey");

        expiryInterval = null;
    }

    @Nonnull
    public static ExpirablePublicKey of(@Nonnull PublicKey publicKey) {
        return new ExpirablePublicKey(publicKey);
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == this) {
            return true;
        }
        if (obj instanceof ExpirablePublicKey) {
            return publicKey.equals(((ExpirablePublicKey) obj).publicKey);
        }
        return false;
    }

    @Nullable
    public Duration getExpiryInterval() {
        return expiryInterval;
    }

    @Nonnull
    public PublicKey getPublicKey() {
        return publicKey;
    }

    @Override
    public int hashCode() {
        return publicKey.hashCode();
    }

    public boolean isExpirable() {
        return expiryInterval != null;
    }

    public static class Builder {

        private final PublicKey publicKey;

        private Duration expiryInterval;

        public Builder(@Nonnull PublicKey publicKey) {
            this.publicKey = requireNonNull(publicKey, "publicKey");
        }

        @Nonnull
        public ExpirablePublicKey build() {
            return new ExpirablePublicKey(this);
        }

        @Nonnull
        public Builder expiryInterval(@Nullable Duration value) {
            if (value == null || value.isNegative() || value.isZero()) {
                expiryInterval = null;
            } else {
                expiryInterval = value;
            }

            return this;
        }
    }
}
