package com.atlassian.bitbucket.mesh.credentials;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.nio.file.Path;
import java.util.Objects;
import java.util.Optional;

import static java.util.Objects.requireNonNull;
import static java.util.Optional.ofNullable;

public class PrivateKeyCredentials implements Credentials {

    private final String passphrase;
    private final Path privateKeyPath;
    private final String username;

    private PrivateKeyCredentials(Builder builder) {
        passphrase = builder.passphrase;
        privateKeyPath = builder.privateKeyPath;
        username = builder.username;
    }

    @Override
    public <T> T accept(@Nonnull CredentialsVisitor<T> visitor) {
        return requireNonNull(visitor, "visitor").visit(this);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        PrivateKeyCredentials that = (PrivateKeyCredentials) o;
        return Objects.equals(passphrase, that.passphrase) &&
               privateKeyPath.equals(that.privateKeyPath) &&
               username.equals(that.username);
    }

    @Nonnull
    public Optional<String> getPassphrase() {
        return ofNullable(passphrase);
    }

    @Nonnull
    public Path getPrivateKeyPath() {
        return privateKeyPath;
    }

    @Nonnull
    public String getUsername() {
        return username;
    }

    @Override
    public int hashCode() {
        return Objects.hash(passphrase, privateKeyPath, username);
    }

    @Override
    public String toString() {
        return "PrivateKeyCredentials{" +
               "privateKeyPath=" + privateKeyPath +
               ", username='" + username + '\'' +
               '}';
    }

    public static class Builder {

        private final Path privateKeyPath;
        private final String username;

        private String passphrase;

        public Builder(@Nonnull String username, @Nonnull Path privateKeyPath) {
            this.privateKeyPath = requireNonNull(privateKeyPath, "privateKeyPath");
            this.username = requireNonNull(username, "username");
        }

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

        @Nonnull
        public Builder passphrase(@Nullable String value) {
            passphrase = value;
            return this;
        }
    }
}
