package com.jscape.inet.ssh.protocol.v2.marshaling.keys;

import com.jscape.inet.ssh.protocol.v2.messages.Signature;

import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import static com.jscape.util.Parameters.assertNotNull;

/**
 * @author Alex Usun
 */
public class ComponentSigner
        implements Signer {

    private final Map<String, Entry> entries;

    public ComponentSigner(Entry... entries) {
        this.entries = new HashMap<>();
        set(entries);
    }

    public ComponentSigner set(Entry... entries) {
        for (Entry entry : entries) {
            this.entries.put(entry.algorithm.toUpperCase(Locale.ENGLISH), entry);
        }

        return this;
    }

    @Override
    public Signature sign(byte[] data, String publicKeyAlgorithm, PrivateKey key)
            throws Exception {
        Entry entry = entryFor(key.getAlgorithm().toUpperCase(Locale.ENGLISH));
        return entry.signer.sign(data, publicKeyAlgorithm, key);
    }

    @Override
    public void assertSignatureValid(byte[] data, PublicKey key, Signature signature)
            throws Exception {
        Entry entry = entryFor(key.getAlgorithm().toUpperCase(Locale.ENGLISH));
        entry.signer.assertSignatureValid(data, key, signature);
    }

    @Override
    public String toString() {
        return "ComponentSigner {"
                + "entries=" + this.entries
                + '}';
    }

    private Entry entryFor(String algorithm) {
        Entry entry = this.entries.get(algorithm.toUpperCase(Locale.ENGLISH));

        if (entry == null) {
            throw new IllegalArgumentException("Unsupported algorithm: " + algorithm);
        }

        return entry;
    }

    public static class Entry {

        public final String algorithm;
        public final Signer signer;

        public Entry(String algorithm, Signer signer) {
            assertNotNull(algorithm);
            this.algorithm = algorithm;

            assertNotNull(signer);
            this.signer = signer;
        }

        @Override
        public String toString() {
            return "Entry {"
                    + "algorithm='" + this.algorithm + '\''
                    + ", signer=" + this.signer
                    + '}';
        }
    }
}
