/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.apache.qpid.server.security;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.PrivateKey;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.naming.InvalidNameException;
import javax.naming.ldap.LdapName;
import javax.naming.ldap.Rdn;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;

import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.apache.qpid.server.configuration.IllegalConfigurationException;
import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.model.ManagedAttributeField;
import org.apache.qpid.server.model.ManagedObject;
import org.apache.qpid.server.model.ManagedObjectFactoryConstructor;
import org.apache.qpid.server.model.State;
import org.apache.qpid.server.model.StateTransition;
import org.apache.qpid.server.util.urlstreamhandler.data.Handler;
import org.apache.qpid.transport.network.security.ssl.SSLUtil;

@ManagedObject( category = false )
public class NonJavaKeyStoreImpl extends AbstractKeyStore<NonJavaKeyStoreImpl> implements NonJavaKeyStore<NonJavaKeyStoreImpl>
{
    private static final Logger LOGGER = LoggerFactory.getLogger(NonJavaKeyStoreImpl.class);

    @ManagedAttributeField( afterSet = "updateKeyManagers" )
    private String _privateKeyUrl;
    @ManagedAttributeField( afterSet = "updateKeyManagers" )
    private String _certificateUrl;
    @ManagedAttributeField( afterSet = "updateKeyManagers" )
    private String _intermediateCertificateUrl;

    private volatile KeyManager[] _keyManagers = new KeyManager[0];

    private static final SecureRandom RANDOM = new SecureRandom();

    static
    {
        Handler.register();
    }

    private X509Certificate _certificate;

    @ManagedObjectFactoryConstructor
    public NonJavaKeyStoreImpl(final Map<String, Object> attributes, Broker<?> broker)
    {
        super(attributes, broker);
    }

    @Override
    public String getPrivateKeyUrl()
    {
        return _privateKeyUrl;
    }

    @Override
    public String getCertificateUrl()
    {
        return _certificateUrl;
    }

    @Override
    public String getIntermediateCertificateUrl()
    {
        return _intermediateCertificateUrl;
    }

    @Override
    public String getSubjectName()
    {
        if(_certificate != null)
        {
            try
            {
                String dn = _certificate.getSubjectX500Principal().getName();
                LdapName ldapDN = new LdapName(dn);
                String name = dn;
                for (Rdn rdn : ldapDN.getRdns())
                {
                    if (rdn.getType().equalsIgnoreCase("CN"))
                    {
                        name = String.valueOf(rdn.getValue());
                        break;
                    }
                }
                return name;
            }
            catch (InvalidNameException e)
            {
                LOGGER.error("Error getting subject name from certificate");
                return null;
            }
        }
        else
        {
            return null;
        }
    }

    @Override
    public Date getCertificateValidEnd()
    {
        return _certificate == null ? null : _certificate.getNotAfter();
    }

    @Override
    public Date getCertificateValidStart()
    {
        return _certificate == null ? null : _certificate.getNotBefore();
    }


    @Override
    public KeyManager[] getKeyManagers() throws GeneralSecurityException
    {

        return _keyManagers;
    }

    @Override
    public void onValidate()
    {
        super.onValidate();
        validateKeyStoreAttributes(this);
    }

    @StateTransition(currentState = {State.ACTIVE, State.ERRORED}, desiredState = State.DELETED)
    protected ListenableFuture<Void> doDelete()
    {
        return deleteIfNotInUse();
    }

    @StateTransition(currentState = {State.UNINITIALIZED, State.ERRORED}, desiredState = State.ACTIVE)
    protected ListenableFuture<Void> doActivate()
    {
        initializeExpiryChecking();
        setState(State.ACTIVE);
        return Futures.immediateFuture(null);
    }

    @Override
    protected void validateChange(final ConfiguredObject<?> proxyForValidation, final Set<String> changedAttributes)
    {
        super.validateChange(proxyForValidation, changedAttributes);
        NonJavaKeyStore changedStore = (NonJavaKeyStore) proxyForValidation;
        if (changedAttributes.contains(NAME) && !getName().equals(changedStore.getName()))
        {
            throw new IllegalConfigurationException("Changing the key store name is not allowed");
        }
        validateKeyStoreAttributes(changedStore);
    }

    private void validateKeyStoreAttributes(NonJavaKeyStore<?> keyStore)
    {
        try
        {
            SSLUtil.readPrivateKey(getUrlFromString(keyStore.getPrivateKeyUrl()));
            SSLUtil.readCertificates(getUrlFromString(keyStore.getCertificateUrl()));
            if(keyStore.getIntermediateCertificateUrl() != null)
            {
                SSLUtil.readCertificates(getUrlFromString(keyStore.getIntermediateCertificateUrl()));
            }
        }
        catch (IOException | GeneralSecurityException e )
        {
            throw new IllegalConfigurationException("Cannot validate private key or certificate(s):" + e, e);
        }
    }

    @SuppressWarnings("unused")
    private void updateKeyManagers()
    {
        try
        {
            if (_privateKeyUrl != null && _certificateUrl != null)
            {
                PrivateKey privateKey = SSLUtil.readPrivateKey(getUrlFromString(_privateKeyUrl));
                X509Certificate[] certs = SSLUtil.readCertificates(getUrlFromString(_certificateUrl));
                if(_intermediateCertificateUrl != null)
                {
                    List<X509Certificate> allCerts = new ArrayList<>(Arrays.asList(certs));
                    allCerts.addAll(Arrays.asList(SSLUtil.readCertificates(getUrlFromString(_intermediateCertificateUrl))));
                    certs = allCerts.toArray(new X509Certificate[allCerts.size()]);
                }
                checkCertificateExpiry(certs);
                java.security.KeyStore inMemoryKeyStore = java.security.KeyStore.getInstance(java.security.KeyStore.getDefaultType());

                byte[] bytes = new byte[64];
                char[] chars = new char[64];
                RANDOM.nextBytes(bytes);
                StandardCharsets.US_ASCII.decode(ByteBuffer.wrap(bytes)).get(chars);
                inMemoryKeyStore.load(null, chars);
                inMemoryKeyStore.setKeyEntry("1", privateKey, chars, certs);


                KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
                kmf.init(inMemoryKeyStore, chars);
                _keyManagers = kmf.getKeyManagers();
                _certificate = certs[0];
            }

        }
        catch (IOException | GeneralSecurityException e)
        {
            throw new IllegalConfigurationException("Cannot load private key or certificate(s): " + e, e);
        }
    }

    protected void checkCertificateExpiry()
    {
        try
        {
            if (_privateKeyUrl != null && _certificateUrl != null)
            {
                X509Certificate[] certs = SSLUtil.readCertificates(getUrlFromString(_certificateUrl));
                if (_intermediateCertificateUrl != null)
                {
                    List<X509Certificate> allCerts = new ArrayList<>(Arrays.asList(certs));
                    allCerts.addAll(Arrays.asList(SSLUtil.readCertificates(getUrlFromString(_intermediateCertificateUrl))));
                    certs = allCerts.toArray(new X509Certificate[allCerts.size()]);
                }
                checkCertificateExpiry(certs);
            }
        }
        catch (GeneralSecurityException | IOException e)
        {
            LOGGER.info("Unexpected exception while trying to check certificate validity", e);
        }
    }

    private void checkCertificateExpiry(final X509Certificate... certificates)
    {
        int expiryWarning = getCertificateExpiryWarnPeriod();
        if(expiryWarning > 0)
        {
            long currentTime = System.currentTimeMillis();
            Date expiryTestDate = new Date(currentTime + (ONE_DAY * (long) expiryWarning));

            checkCertificatesExpiry(currentTime, expiryTestDate, certificates);
        }
    }

    private URL getUrlFromString(String urlString) throws MalformedURLException
    {
        URL url;

        try
        {
            url = new URL(urlString);
        }
        catch (MalformedURLException e)
        {
            File file = new File(urlString);
            url = file.toURI().toURL();

        }
        return url;
    }

}
