package com.jscape.filetransfer;

import com.jscape.util.Parameters;

import javax.net.ssl.HandshakeCompletedEvent;
import javax.net.ssl.SSLPeerUnverifiedException;
import javax.net.ssl.SSLSession;
import javax.security.cert.X509Certificate;
import java.security.Principal;
import java.security.cert.Certificate;

/**
 * A SSL handshake event. Provides information about current SSL connection in SSL-based transfers.
 *
 * @author Alex Usun
 */
public class FileTransferSslHandshakeEvent
        extends FileTransferEvent {

    private final HandshakeCompletedEvent baseEvent;

    /**
     * Creates a new event instance.
     *
     * @param source    an event source
     * @param baseEvent a base event
     */
    public FileTransferSslHandshakeEvent(FileTransfer source, HandshakeCompletedEvent baseEvent) {
        super(source);

        Parameters.assertNotNull(baseEvent);
        this.baseEvent = baseEvent;
    }

    /**
     * Returns the session that triggered this event.
     *
     * @return the SSLSession for this handshake
     */
    public SSLSession getSession() {
        return this.baseEvent.getSession();
    }

    /**
     * Returns the cipher suite in use by the session which was produced by the handshake.
     *
     * @return the name of the cipher suite negotiated during this session
     */
    public String getCipherSuite() {
        return this.baseEvent.getCipherSuite();
    }

    /**
     * Returns the certificate(s) that were sent to the peer during handshaking.
     *
     * @return an ordered array of certificates, with the local certificate first followed by any certificate authorities.
     *         If no certificates were sent, then null is returned
     */
    public Certificate[] getLocalCertificates() {
        return this.baseEvent.getLocalCertificates();
    }

    /**
     * Returns the identity of the peer which was established as part of defining the session.
     *
     * @return an ordered array of the peer certificates, with the peer's own certificate first followed by any certificate authorities.
     *         If no certificates were received, then null is returned
     */
    public Certificate[] getPeerCertificates() {
        try {
            return this.baseEvent.getPeerCertificates();
        } catch (SSLPeerUnverifiedException e) {
            return null;
        }
    }

    /**
     * Returns the identity of the peer which was identified as part of defining the session.
     *
     * @return an ordered array of peer X.509 certificates, with the peer's own certificate first followed by any certificate authorities.
     *         If no certificates were received, then null is returned
     */
    public X509Certificate[] getPeerCertificateChain() {
        try {
            return this.baseEvent.getPeerCertificateChain();
        } catch (SSLPeerUnverifiedException e) {
            return null;
        }
    }

    /**
     * Returns the identity of the peer which was established as part of defining the session.
     *
     * @return the peer's principal. Returns an X500Principal of the end-entity certiticate for X509-based cipher suites, and KerberosPrincipal for Kerberos cipher suites.
     *         If no principal was received, then null is returned.
     */
    public Principal getPeerPrincipal() {
        try {
            return this.baseEvent.getPeerPrincipal();
        } catch (SSLPeerUnverifiedException e) {
            return null;
        }
    }

    /**
     * Returns the principal that was sent to the peer during handshaking.
     *
     * @return the principal sent to the peer. Returns an X500Principal of the end-entity certificate for X509-based cipher suites, and KerberosPrincipal for Kerberos cipher suites.
     *         If no principal was sent, then null is returned.
     */
    public Principal getLocalPrincipal() {
        return this.baseEvent.getLocalPrincipal();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void accept(FileTransferListener listener) {
        listener.sslHandshakeCompleted(this);
    }

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