/*
 *
 * 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.ByteArrayInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.lang.reflect.InvocationTargetException;
import java.net.InetAddress;
import java.net.InterfaceAddress;
import java.net.NetworkInterface;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.SecureRandom;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.security.spec.InvalidKeySpecException;
import java.util.Arrays;
import java.util.Base64;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

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.apache.qpid.server.configuration.IllegalConfigurationException;
import org.apache.qpid.server.logging.EventLogger;
import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.model.Content;
import org.apache.qpid.server.model.CustomRestHeaders;
import org.apache.qpid.server.model.ManagedAttributeField;
import org.apache.qpid.server.model.ManagedObjectFactoryConstructor;
import org.apache.qpid.server.model.RestContentHeader;
import org.apache.qpid.server.model.State;
import org.apache.qpid.server.model.StateTransition;
import org.apache.qpid.server.transport.network.security.ssl.SSLUtil;
import org.apache.qpid.server.util.Strings;

public class AutoGeneratedSelfSignedKeyStoreImpl
        extends AbstractKeyStore<AutoGeneratedSelfSignedKeyStoreImpl>
        implements AutoGeneratedSelfSignedKeyStore<AutoGeneratedSelfSignedKeyStoreImpl>
{

    private static final SecureRandom RANDOM = new SecureRandom();

    private final Broker<?> _broker;
    private final EventLogger _eventLogger;

    @ManagedAttributeField
    private volatile String _keyAlgorithm;
    @ManagedAttributeField
    private volatile String _signatureAlgorithm;
    @ManagedAttributeField
    private volatile int _keyLength;
    @ManagedAttributeField
    private volatile int _durationInMonths;

    private volatile PrivateKey _privateKey;
    private volatile X509Certificate _certificate;
    private volatile KeyManager[] _keyManagers;

    private volatile boolean _generated;
    private volatile boolean _created;


    @ManagedObjectFactoryConstructor(conditionallyAvailable = true)
    public AutoGeneratedSelfSignedKeyStoreImpl(final Map<String, Object> attributes, Broker<?> broker)
    {
        super(attributes, broker);
        _broker = broker;
        _eventLogger = _broker.getEventLogger();
    }

    @Override
    public KeyManager[] getKeyManagers() throws GeneralSecurityException
    {
        KeyManager[] keyManagers = _keyManagers;
        return keyManagers == null ? new KeyManager[0] : Arrays.copyOf(keyManagers, keyManagers.length);
    }

    @Override
    public String getKeyAlgorithm()
    {
        return _keyAlgorithm;
    }

    @Override
    public String getSignatureAlgorithm()
    {
        return _signatureAlgorithm;
    }

    @Override
    public int getKeyLength()
    {
        return _keyLength;
    }

    @Override
    public int getDurationInMonths()
    {
        return _durationInMonths;
    }

    @Override
    public String getEncodedCertificate()
    {
        try
        {
            return Base64.getEncoder().encodeToString(_certificate.getEncoded());
        }
        catch (CertificateEncodingException e)
        {
            throw new IllegalConfigurationException("Cannot encode certificate", e);
        }
    }

    @Override
    public String getEncodedPrivateKey()
    {
        return Base64.getEncoder().encodeToString(_privateKey.getEncoded());
    }

    @Override
    protected void postResolve()
    {
        super.postResolve();
        if(getActualAttributes().containsKey(ENCODED_PRIVATE_KEY) && getActualAttributes().containsKey(ENCODED_CERTIFICATE))
        {
            loadPrivateKeyAndCertificate();
        }
        else
        {
            generatePrivateKeyAndCertificate();
        }
        generateKeyManagers();

    }

    private void loadPrivateKeyAndCertificate()
    {
        byte[] privateKeyEncoded = Strings.decodeBase64((String) getActualAttributes().get(ENCODED_PRIVATE_KEY));
        byte[] certificateEncoded = Strings.decodeBase64((String) getActualAttributes().get(
                ENCODED_CERTIFICATE));


        try(ByteArrayInputStream input = new ByteArrayInputStream(certificateEncoded))
        {
            _certificate = (X509Certificate) SSLUtil.getCertificateFactory().generateCertificate(input);
        }
        catch (CertificateException | IOException e)
        {
            throw new IllegalConfigurationException("Could not decode certificate", e);
        }

        try
        {
            _privateKey = SSLUtil.readPrivateKey(privateKeyEncoded, _keyAlgorithm);
        }
        catch (NoSuchAlgorithmException | InvalidKeySpecException e)
        {
            throw new IllegalConfigurationException("Could not decode private key", e);
        }
    }

    @Override
    protected void onCreate()
    {
        super.onCreate();
        _created = true;
    }

    @Override
    protected void onOpen()
    {
        super.onOpen();
        initializeExpiryChecking();
    }

    @StateTransition(currentState = { State.UNINITIALIZED, State.STOPPED, State.ERRORED}, desiredState = State.ACTIVE)
    protected ListenableFuture<Void> activate()
    {
        if(!_created)
        {
            saveDerivedAttributesIfNecessary();
        }
        setState(State.ACTIVE);

        return Futures.immediateFuture(null);
    }

    private void saveDerivedAttributesIfNecessary()
    {
        if(_generated)
        {

            final Object encodedCertificate = getEncodedCertificate();
            attributeSet(ENCODED_CERTIFICATE, encodedCertificate, encodedCertificate);

            final Object encodedPrivateKey = getEncodedPrivateKey();
            attributeSet(ENCODED_PRIVATE_KEY, encodedPrivateKey, encodedPrivateKey);

            _generated = false;
        }
    }

    private void generatePrivateKeyAndCertificate()
    {
        try
        {


            Set<InetAddress> addresses = new HashSet<>();
            for (NetworkInterface networkInterface : Collections.list(NetworkInterface.getNetworkInterfaces()))
            {
                for (InterfaceAddress inetAddress : networkInterface.getInterfaceAddresses())
                {
                    addresses.add(inetAddress.getAddress());
                }
            }

            Set<String> dnsNames = new HashSet<>();

            for(InetAddress address : addresses)
            {

                String hostName = address.getHostName();
                if (hostName != null)
                {
                    dnsNames.add(hostName);
                }
                String canonicalHostName = address.getCanonicalHostName();
                if (canonicalHostName != null)
                {
                    dnsNames.add(canonicalHostName);
                }
            }

            long startTime = System.currentTimeMillis();
            Calendar calendar = Calendar.getInstance();
            calendar.setTimeInMillis(startTime);
            calendar.add(Calendar.MONTH, _durationInMonths);
            long duration = (calendar.getTimeInMillis() - startTime)/1000;

            final SSLUtil.KeyCertPair keyCertPair = SSLUtil.generateSelfSignedCertificate(_keyAlgorithm,
                                                                                          _signatureAlgorithm,
                                                                                          _keyLength,
                                                                                          startTime,
                                                                                          duration,
                                                                                          "CN=Qpid",
                                                                                          dnsNames,
                                                                                          addresses);

            _privateKey = keyCertPair.getPrivateKey();
            _certificate = keyCertPair.getCertificate();
            _generated = true;

        }
        catch (InstantiationException | IllegalAccessException | InvocationTargetException | IOException e)
        {
            throw new IllegalConfigurationException("Unable to construct keystore", e);
        }
    }

    @Override
    protected void checkCertificateExpiry()
    {
        int expiryWarning = getCertificateExpiryWarnPeriod();
        if(expiryWarning > 0)
        {
            long currentTime = System.currentTimeMillis();
            Date expiryTestDate = new Date(currentTime + (ONE_DAY * (long) expiryWarning));

            checkCertificatesExpiry(currentTime, expiryTestDate,
                                    new X509Certificate[]{_certificate});
        }
    }

    @Override
    protected Collection<Certificate> getCertificates()
    {
        return Collections.singleton(_certificate);
    }


    private void generateKeyManagers()
    {
        try
        {
            X509Certificate[] certs = new X509Certificate[] { _certificate };


            java.security.KeyStore inMemoryKeyStore = java.security.KeyStore.getInstance(java.security.KeyStore.getDefaultType());

            byte[] bytes = new byte[64];
            char[] chars = "".toCharArray();
            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();

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



    static boolean isAvailable()
    {
        return SSLUtil.canGenerateCerts();
    }

    @Override
    public void regenerateCertificate()
    {
        generatePrivateKeyAndCertificate();
        saveDerivedAttributesIfNecessary();
    }

    @Override
    public Content getClientTrustStore(String password)
    {

        try
        {
            KeyStore inMemoryKeyStore =
                    KeyStore.getInstance(KeyStore.getDefaultType());

            inMemoryKeyStore.load(null, null);
            inMemoryKeyStore.setCertificateEntry(getName(), _certificate);

            return new TrustStoreContent(inMemoryKeyStore, getName(), password == null ? new char[0] : password.toCharArray());
        }
        catch (CertificateException | NoSuchAlgorithmException | IOException | KeyStoreException e)
        {
            throw new IllegalArgumentException(e);
        }
    }


    @Override
    public Content getCertificate()
    {
        try
        {
            return new CertificateContent(_certificate, getName());
        }
        catch (CertificateEncodingException e)
        {
            throw new IllegalArgumentException("Cannot decode encode the certificate");
        }

    }

    private static class TrustStoreContent implements Content, CustomRestHeaders
    {
        private final KeyStore _keyStore;
        private final char[] _password;
        private final String _disposition;

        public TrustStoreContent(final KeyStore inMemoryKeyStore,
                                 final String name, final char[] password)
        {
            _keyStore = inMemoryKeyStore;
            _password = password;
            _disposition = "attachment; filename=\"" + name + ".jks\"";
        }

        @Override
        public void write(final OutputStream outputStream) throws IOException
        {
            try
            {
                _keyStore.store(outputStream, _password);
            }
            catch (KeyStoreException | NoSuchAlgorithmException | CertificateException e)
            {
                throw new IllegalArgumentException(e);
            }
        }

        @Override
        public void release()
        {
        }

        @RestContentHeader("Content-Type")
        public String getContentType()
        {
            return "application/octet-stream";
        }

        @RestContentHeader("Content-Disposition")
        public String getContentDisposition()
        {
            return _disposition;
        }

    }

    private static class CertificateContent implements Content, CustomRestHeaders
    {

        private final String _disposition;
        private final String _certString;

        public CertificateContent(final X509Certificate certificate, final String name)
                throws CertificateEncodingException
        {
            _disposition = "attachment; filename=\"" + name + ".pem\"";
            StringBuilder certStringBuffer = new StringBuilder("-----BEGIN CERTIFICATE-----\n");
            String cert = Base64.getEncoder().encodeToString(certificate.getEncoded());
            int offset = 0;
            while(cert.length()-offset > 64)
            {
                certStringBuffer.append(cert.substring(offset, offset+64));
                offset+=64;
                certStringBuffer.append("\n");
            }
            certStringBuffer.append(cert.substring(offset));
            certStringBuffer.append("\n-----END CERTIFICATE-----\n");
            _certString = certStringBuffer.toString();
        }

        @Override
        public void write(final OutputStream outputStream) throws IOException
        {
            Writer w = new OutputStreamWriter(outputStream);
            w.write(_certString);
            w.flush();
        }

        @Override
        public void release()
        {
        }

        @RestContentHeader("Content-Type")
        public String getContentType()
        {
            return "text/plain";
        }

        @RestContentHeader("Content-Disposition")
        public String getContentDisposition()
        {
            return _disposition;
        }


    }

}
