/*
 * Identity.java
 * Copyright 2017 Rob Spoor
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.github.robtimus.filesystems.sftp;

import java.io.File;
import java.util.Objects;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;

/**
 * A combination of a private and public key.
 *
 * @author Rob Spoor
 * @since 1.2
 */
public abstract class Identity {

    private Identity() {
        // private constructor to prevent direct initialization
    }

    abstract void addIdentity(JSch jsch) throws JSchException;

    /**
     * Creates a key pair from private key and public key files.
     * The public key file will be the private key file with {@code .pub} appended to the name.
     *
     * @param privateKeyFile The private key file.
     * @return The created key pair.
     */
    public static Identity fromFiles(final File privateKeyFile) {
        Objects.requireNonNull(privateKeyFile);
        return new Identity() {

            @Override
            void addIdentity(JSch jsch) throws JSchException {
                jsch.addIdentity(privateKeyFile.getAbsolutePath());
            }
        };
    }

    /**
     * Creates a key pair from private key and public key files.
     * The public key file will be the private key file with {@code .pub} appended to the name.
     *
     * @param privateKeyFile The private key file.
     * @param passphrase The passphrase for the private key.
     * @return The created key pair.
     */
    public static Identity fromFiles(final File privateKeyFile, final String passphrase) {
        Objects.requireNonNull(privateKeyFile);
        return new Identity() {

            @Override
            void addIdentity(JSch jsch) throws JSchException {
                jsch.addIdentity(privateKeyFile.getAbsolutePath(), passphrase);
            }
        };
    }

    /**
     * Creates a key pair from private key and public key files.
     * The public key file will be the private key file with {@code .pub} appended to the name.
     *
     * @param privateKeyFile The private key file.
     * @param passphrase The passphrase for the private key.
     * @return The created key pair.
     */
    public static Identity fromFiles(final File privateKeyFile, final byte[] passphrase) {
        Objects.requireNonNull(privateKeyFile);
        return new Identity() {

            @Override
            void addIdentity(JSch jsch) throws JSchException {
                jsch.addIdentity(privateKeyFile.getAbsolutePath(), passphrase);
            }
        };
    }

    /**
     * Creates a key pair from private key and public key files.
     *
     * @param privateKeyFile The private key file.
     * @param publicKeyFile The public key file.
     * @param passphrase The passphrase for the private key.
     * @return The created key pair.
     */
    public static Identity fromFiles(final File privateKeyFile, final File publicKeyFile, final byte[] passphrase) {
        Objects.requireNonNull(privateKeyFile);
        return new Identity() {

            @Override
            void addIdentity(JSch jsch) throws JSchException {
                jsch.addIdentity(privateKeyFile.getAbsolutePath(), publicKeyFile == null ? null : publicKeyFile.getAbsolutePath(), passphrase);
            }
        };
    }

    /**
     * Creates a key pair from a private key and public key.
     *
     * @param name The name of the key pair.
     * @param privateKey The private key data.
     * @param publicKey The public key data.
     * @param passphrase The passphrase for the private key.
     * @return The created key pair.
     * @since 1.4
     */
    public static Identity fromData(final String name, final byte[] privateKey, final byte[] publicKey, final byte[] passphrase) {
        Objects.requireNonNull(name);
        Objects.requireNonNull(privateKey);
        return new Identity() {

            @Override
            void addIdentity(JSch jsch) throws JSchException {
                jsch.addIdentity(name, privateKey, publicKey, passphrase);
            }
        };
    }
}

@@ -865,24 +865,21 @@
 %0Apublic 
-abstract
+final
  class I
@@ -905,84 +905,117 @@
 ate 
-Identity() %7B%0A        // private constructor to prevent direct initialization
+final JSchConsumer consumer;%0A%0A    private Identity(JSchConsumer consumer) %7B%0A        this.consumer = consumer;
 %0A   
@@ -1026,17 +1026,8 @@
     
-abstract 
 void
@@ -1070,17 +1070,55 @@
 xception
-;
+ %7B%0A        consumer.accept(jsch);%0A    %7D
 %0A%0A    /*
@@ -1529,113 +1529,15 @@
 ity(
-) %7B%0A%0A            @Override%0A            void addIdentity(JSch jsch) throws JSchException %7B%0A               
+jsch -%3E
  jsc
@@ -1587,33 +1587,9 @@
 h())
-;%0A            %7D%0A        %7D
+)
 ;%0A  
@@ -2097,113 +2097,15 @@
 ity(
-) %7B%0A%0A            @Override%0A            void addIdentity(JSch jsch) throws JSchException %7B%0A               
+jsch -%3E
  jsc
@@ -2167,33 +2167,9 @@
 ase)
-;%0A            %7D%0A        %7D
+)
 ;%0A  
@@ -2677,113 +2677,15 @@
 ity(
-) %7B%0A%0A            @Override%0A            void addIdentity(JSch jsch) throws JSchException %7B%0A               
+jsch -%3E
  jsc
@@ -2747,33 +2747,9 @@
 ase)
-;%0A            %7D%0A        %7D
+)
 ;%0A  
@@ -3216,133 +3216,136 @@
     
-return new Identity() %7B%0A%0A            @Override%0A            void addIdentity(JSch jsch) throws JSchException %7B%0A               
+final String publicKeyPath = publicKeyFile == null ? null : publicKeyFile.getAbsolutePath();%0A        return new Identity(jsch -%3E
  jsc
@@ -3405,61 +3405,12 @@
 cKey
-File == null ? null : publicKeyFile.getAbsolute
 Path
-()
 , pa
@@ -3422,33 +3422,9 @@
 ase)
-;%0A            %7D%0A        %7D
+)
 ;%0A  
@@ -4010,113 +4010,15 @@
 ity(
-) %7B%0A%0A            @Override%0A            void addIdentity(JSch jsch) throws JSchException %7B%0A               
+jsch -%3E
  jsc
@@ -4075,33 +4075,107 @@
 ase)
+)
 ;%0A    
+%7D%0A%0A
     
-    %7D%0A        %7D
+private interface JSchConsumer %7B%0A%0A        void accept(JSch jsch) throws JSchException
 ;%0A  

Make more use of lambdas