package com.jscape.inet.ssh.protocol.v2.messages;

import java.security.Key;
import java.util.List;
import java.util.Locale;

import static com.jscape.util.CollectionTools.list;

/**
 * @author Alex Usun
 */
public enum PublicKeyAlgorithm {

    RSA("ssh-rsa", "RSA", "SHA1"),
    RSA_256("rsa-sha2-256", "RSA", "SHA256"),
    RSA_512("rsa-sha2-512", "RSA", "SHA512"),
    DSA("ssh-dss", "DSA", "SHA1"),
    NIST_P_256("ecdsa-sha2-nistp256", "EC", ""),
    NIST_P_384("ecdsa-sha2-nistp384", "EC",""),
    NIST_P_521("ecdsa-sha2-nistp521", "EC", ""),
    NIST_K_163("ecdsa-sha2-1.3.132.0.1", "EC", ""),
    NIST_P_192("ecdsa-sha2-1.2.840.10045.3.1.1", "EC", ""),
    NIST_P_224("ecdsa-sha2-1.3.132.0.33", "EC", ""),
    NIST_K_233("ecdsa-sha2-1.3.132.0.26", "EC", ""),
    NIST_B_233("ecdsa-sha2-1.3.132.0.27", "EC", ""),
    NIST_K_283("ecdsa-sha2-1.3.132.0.16", "EC", ""),
    NIST_K_409("ecdsa-sha2-1.3.132.0.36", "EC", ""),
    NIST_B_409("ecdsa-sha2-1.3.132.0.37", "EC", ""),
    NIST_T_571("ecdsa-sha2-1.3.132.0.38", "EC", "");

    public final String identifier;
    public final String keyAlgorithm;
    public final String signatureAlgorithm;

    public static PublicKeyAlgorithm algorithmFor(Key key) {
        for (PublicKeyAlgorithm candidate : values()) {
            if (key.getAlgorithm().equalsIgnoreCase(candidate.keyAlgorithm)) {
                return candidate;
            }
        }

        throw new IllegalArgumentException(String.format("Unsupported key type: %s.", key));
    }

    public static List<String> algorithmIdentifiersFor(Key key) {
        switch (key.getAlgorithm().toUpperCase(Locale.ENGLISH)) {
            case "RSA":
                return list(RSA.identifier, RSA_256.identifier, RSA_512.identifier);
            case "DSA":
                return list(DSA.identifier);
            case "EC":
            case "ECDSA":
                String curveIdentifier = NamedEllipticCurveDomainParameters.identifierFor(key);
                return list(String.format("ecdsa-sha2-%s", curveIdentifier));
            default:
                throw new IllegalArgumentException(String.format("Unsupported key type: %s.", key));
        }
    }

    public static String formatIdentifierFor(Key key) {
        switch (key.getAlgorithm().toUpperCase(Locale.ENGLISH)) {
            case "RSA":
                return RSA.identifier;
            case "DSA":
                return DSA.identifier;
            case "EC":
            case "ECDSA":
                String curveIdentifier = NamedEllipticCurveDomainParameters.identifierFor(key);
                return String.format("ecdsa-sha2-%s", curveIdentifier);
            default:
                throw new IllegalArgumentException(String.format("Unsupported key type: %s.", key));
        }
    }

    public static String signatureAlgorithmFor(String identifier) {
        for (PublicKeyAlgorithm candidate : values()) {
            if (candidate.identifier.equalsIgnoreCase(identifier)) {
                return candidate.signatureAlgorithm;
            }
        }

        throw new IllegalArgumentException(String.format("Unsupported public key algorithm: %s.", identifier));
    }

    PublicKeyAlgorithm(String identifier, String keyAlgorithm, String signatureAlgorithm) {
        this.identifier = identifier;
        this.keyAlgorithm = keyAlgorithm;
        this.signatureAlgorithm = signatureAlgorithm;
    }
}
