/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * 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 org.conscrypt;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import javax.crypto.SecretKey;

public class OpenSSLEngine {
    static {
        if (!NativeCrypto.isBoringSSL) {
            NativeCrypto.ENGINE_load_dynamic();
        }
    }

    private static final Object mLoadingLock = new Object();

    /** The ENGINE's native handle. */
    private final long ctx;

    /**
     * BoringSSL doesn't really use ENGINE objects, so we just keep this single
     * instance around to satisfy API calls.
     */
    private static class BoringSSL {
        public static final OpenSSLEngine INSTANCE = new OpenSSLEngine();
    }

    public static OpenSSLEngine getInstance(String engine) throws IllegalArgumentException {
        if (NativeCrypto.isBoringSSL) {
            return BoringSSL.INSTANCE;
        }

        if (engine == null) {
            throw new NullPointerException("engine == null");
        }

        final long engineCtx;
        synchronized (mLoadingLock) {
            engineCtx = NativeCrypto.ENGINE_by_id(engine);
            if (engineCtx == 0) {
                throw new IllegalArgumentException("Unknown ENGINE id: " + engine);
            }

            NativeCrypto.ENGINE_add(engineCtx);
        }

        return new OpenSSLEngine(engineCtx);
    }

    /**
     * Used for BoringSSL. It doesn't use ENGINEs so there is no native pointer
     * to keep track of.
     */
    private OpenSSLEngine() {
        ctx = 0L;
    }

    /**
     * Used when OpenSSL is in use. It uses an ENGINE instance so we need to
     * keep track if the native pointer for later freeing.
     *
     * @param engineCtx the ENGINE's native handle
     */
    private OpenSSLEngine(long engineCtx) {
        ctx = engineCtx;

        if (NativeCrypto.ENGINE_init(engineCtx) == 0) {
            NativeCrypto.ENGINE_free(engineCtx);
            throw new IllegalArgumentException("Could not initialize engine");
        }
    }

    public PrivateKey getPrivateKeyById(String id) throws InvalidKeyException {
        if (id == null) {
            throw new NullPointerException("id == null");
        }

        final long keyRef = NativeCrypto.ENGINE_load_private_key(ctx, id);
        if (keyRef == 0) {
            return null;
        }

        OpenSSLKey pkey = new OpenSSLKey(keyRef, this, id);
        try {
            return pkey.getPrivateKey();
        } catch (NoSuchAlgorithmException e) {
            throw new InvalidKeyException(e);
        }
    }

    public SecretKey getSecretKeyById(String id, String algorithm) throws InvalidKeyException {
        if (id == null) {
            throw new NullPointerException("id == null");
        }

        final long keyRef = NativeCrypto.ENGINE_load_private_key(ctx, id);
        if (keyRef == 0) {
            return null;
        }

        OpenSSLKey pkey = new OpenSSLKey(keyRef, this, id);
        try {
            return pkey.getSecretKey(algorithm);
        } catch (NoSuchAlgorithmException e) {
            throw new InvalidKeyException(e);
        }
    }

    long getEngineContext() {
        return ctx;
    }

    @Override
    protected void finalize() throws Throwable {
        try {
            if (!NativeCrypto.isBoringSSL) {
                NativeCrypto.ENGINE_finish(ctx);
                NativeCrypto.ENGINE_free(ctx);
            }
        } finally {
            super.finalize();
        }
    }

    @Override
    public boolean equals(Object o) {
        if (o == this) {
            return true;
        }

        if (!(o instanceof OpenSSLEngine)) {
            return false;
        }

        OpenSSLEngine other = (OpenSSLEngine) o;

        if (other.getEngineContext() == ctx) {
            return true;
        }

        final String id = NativeCrypto.ENGINE_get_id(ctx);
        if (id == null) {
            return false;
        }

        return id.equals(NativeCrypto.ENGINE_get_id(other.getEngineContext()));
    }

    @Override
    public int hashCode() {
      return (int) ctx;
    }
}
