/*
 * 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.meecrowave.letencrypt;

import static java.util.Optional.ofNullable;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.util.Objects;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.BiConsumer;
import java.util.stream.Stream;

import org.apache.coyote.http11.AbstractHttp11Protocol;
import org.apache.meecrowave.logging.tomcat.LogFacade;
import org.apache.meecrowave.runner.Cli;
import org.apache.meecrowave.runner.cli.CliOption;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.bouncycastle.openssl.jcajce.JcaPEMWriter;
import org.shredzone.acme4j.Account;
import org.shredzone.acme4j.AccountBuilder;
import org.shredzone.acme4j.Authorization;
import org.shredzone.acme4j.Certificate;
import org.shredzone.acme4j.Order;
import org.shredzone.acme4j.Session;
import org.shredzone.acme4j.Status;
import org.shredzone.acme4j.challenge.Challenge;
import org.shredzone.acme4j.challenge.Http01Challenge;
import org.shredzone.acme4j.exception.AcmeException;
import org.shredzone.acme4j.util.CSRBuilder;

// we depend on bouncycastle but user myst add it to be able to use that
// todo: check we can get rid of it and use jaxrs client instead of acme lib
public class LetsEncryptReloadLifecycle implements AutoCloseable, Runnable {

    private final AtomicReference<LogFacade> logger = new AtomicReference<>();

    private final AbstractHttp11Protocol<?> protocol;

    private final ScheduledExecutorService thread;

    private final ScheduledFuture<?> refreshTask;

    private final LetsEncryptConfig config;

    private final BiConsumer<String, String> challengeUpdater;

    public LetsEncryptReloadLifecycle(final LetsEncryptConfig config, final AbstractHttp11Protocol<?> protocol,
                                      final BiConsumer<String, String> challengeUpdater) {
        this.config = config;
        this.config.init();
        this.protocol = protocol;
        this.challengeUpdater = challengeUpdater;

        final SecurityManager s = System.getSecurityManager();
        final ThreadGroup group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
        this.thread = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {

            @Override
            public Thread newThread(final Runnable r) {
                final Thread newThread = new Thread(group, r, LetsEncryptReloadLifecycle.class.getName() + "_" + hashCode());
                newThread.setDaemon(false);
                newThread.setPriority(Thread.NORM_PRIORITY);
                newThread.setContextClassLoader(getClass().getClassLoader());
                return newThread;
            }
        });
        refreshTask = this.thread.scheduleAtFixedRate(this, 0L, config.getRefreshInterval(), TimeUnit.SECONDS);
    }

    @Override
    public synchronized void run() {
        final KeyPair userKeyPair = loadOrCreateKeyPair(config.getUserKeySize(), config.getUserKeyLocation());
        final KeyPair domainKeyPair = loadOrCreateKeyPair(config.getDomainKeySize(), config.getDomainKey());

        final Session session = new Session(config.getEndpoint());
        try {
            final Account account = new AccountBuilder().agreeToTermsOfService().useKeyPair(userKeyPair).create(session);
            final Order order = account.newOrder().domains(config.getDomains().trim().split(",")).create();
            final boolean updated = order.getAuthorizations().stream().map(authorization -> {
                try {
                    return authorize(authorization);
                } catch (final AcmeException e) {
                    getLogger().error(e.getMessage(), e);
                    return false;
                }
            }).reduce(false, (previous, val) -> previous || val);
            if (!updated) {
                return;
            }

            final CSRBuilder csrBuilder = new CSRBuilder();
            csrBuilder.addDomains(config.getDomains());
            csrBuilder.sign(domainKeyPair);

            try (final Writer writer = new BufferedWriter(new FileWriter(config.getDomainCertificate()))) {
                csrBuilder.write(writer);
            }

            order.execute(csrBuilder.getEncoded());

            try {
                int attempts = config.getRetryCount();
                while (order.getStatus() != Status.VALID && attempts-- > 0) {
                    if (order.getStatus() == Status.INVALID) {
                        throw new AcmeException("Order failed... Giving up.");
                    }
                    Thread.sleep(config.getRetryTimeoutMs());
                    order.update();
                }
            } catch (final InterruptedException ex) {
                getLogger().error(ex.getMessage());
                Thread.currentThread().interrupt();
                return;
            }

            final Certificate certificate = order.getCertificate();
            getLogger().info("Got new certificate " + certificate.getLocation() + " for domain(s) " + config.getDomains());

            try (final Writer writer = new BufferedWriter(new FileWriter(config.getDomainChain()))) {
                certificate.writeCertificate(writer);
            }

            protocol.reloadSslHostConfigs();
        } catch (final AcmeException | IOException ex) {
            getLogger().error(ex.getMessage(), ex);
        }
    }

    private LogFacade getLogger() {
        LogFacade logFacade = logger.get();
        if (logFacade == null) {
            logFacade = new LogFacade(getClass().getName());
            // ok to use 2 instances since the backing instance will be the same, so ignore returned value
            logger.compareAndSet(null, logFacade);
        }
        return logFacade;
    }

    @Override
    public void close() {
        ofNullable(refreshTask).ifPresent(t -> t.cancel(true));
        ofNullable(thread).ifPresent(ExecutorService::shutdownNow);
        try {
            thread.awaitTermination(5, TimeUnit.SECONDS);
        } catch (final InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }

    private boolean authorize(final Authorization authorization) throws AcmeException {
        final Challenge challenge = httpChallenge(authorization);
        if (challenge == null) {
            throw new AcmeException("HTTP challenge is null");
        }
        if (challenge.getStatus() == Status.VALID) {
            return false;
        }

        challenge.trigger();

        try {
            int attempts = config.getRetryCount();
            while (challenge.getStatus() != Status.VALID && attempts-- > 0) {
                if (challenge.getStatus() == Status.INVALID) {
                    throw new AcmeException("Invalid challenge status, exiting refresh iteration");
                }

                Thread.sleep(config.getRetryTimeoutMs());
                challenge.update();
            }
        } catch (final InterruptedException ex) {
            Thread.currentThread().interrupt();
        }

        if (challenge.getStatus() != Status.VALID) {
            throw new AcmeException("Challenge for domain " + authorization.getDomain() + ", is invalid, exiting iteration");
        }
        return true;
    }

    private Challenge httpChallenge(final Authorization auth) throws AcmeException {
        final Http01Challenge challenge = auth.findChallenge(Http01Challenge.TYPE);
        if (challenge == null) {
            throw new AcmeException("Challenge is null");
        }

        challengeUpdater.accept("/.well-known/acme-challenge/" + challenge.getToken(), challenge.getAuthorization());
        return challenge;
    }

    private KeyPair loadOrCreateKeyPair(final int keySize, final File file) {
        if (file.exists()) {
            try (final PEMParser parser = new PEMParser(new FileReader(file))) {
                return new JcaPEMKeyConverter().getKeyPair(PEMKeyPair.class.cast(parser.readObject()));
            } catch (final IOException ex) {
                throw new IllegalStateException("Can't read PEM file: " + file, ex);
            }
        } else {
            try {
                final KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
                keyGen.initialize(keySize);
                final KeyPair keyPair = keyGen.generateKeyPair();
                try (final JcaPEMWriter writer = new JcaPEMWriter(new FileWriter(file))) {
                    writer.writeObject(keyPair);
                } catch (final IOException ex) {
                    throw new IllegalStateException("Can't read PEM file: " + file, ex);
                }
                return keyPair;
            } catch (final NoSuchAlgorithmException ex) {
                throw new IllegalStateException(ex);
            }
        }
    }

    public static class LetsEncryptConfig implements Cli.Options {

        @CliOption(name = "letsencrypt-refresh-interval", description = "Number of second between let'sencrypt refreshes")
        private long refreshInterval = 60;

        @CliOption(name = "letsencrypt-domains", description = "Comma separated list of domains to manage")
        private String domains;

        @CliOption(name = "letsencrypt-key-user-location", description = "Where the user key must be stored")
        private File userKeyLocation;

        @CliOption(name = "letsencrypt-key-user-size", description = "User key size")
        private int userKeySize = 2048;

        @CliOption(name = "letsencrypt-key-domain-location", description = "Where the domain key must be stored")
        private File domainKey;

        @CliOption(name = "letsencrypt-key-domain-size", description = "Domain key size")
        private int domainKeySize = 2048;

        @CliOption(name = "letsencrypt-certificate-domain-location", description = "Where the domain certificate must be stored")
        private File domainCertificate;

        @CliOption(name = "letsencrypt-chain-domain-location", description = "Where the domain chain must be stored")
        private File domainChain;

        @CliOption(name = "letsencrypt-endpoint", description = "Endpoint to use to get the certificates")
        private String endpoint;

        @CliOption(name = "letsencrypt-endpoint-staging", description = "Ignore if endpoint is set, otherwise it set the endpoint accordingly")
        private boolean staging = false;

        @CliOption(name = "letsencrypt-retry-timeout-ms", description = "How long to wait before retrying to get the certificate, default is 3s")
        private long retryTimeoutMs = 3000;

        @CliOption(name = "letsencrypt-retry-count", description = "How many retries to do")
        private int retryCount = 20;

        public void init() {
            if (userKeyLocation == null) {
                userKeyLocation = new File(System.getProperty("catalina.base"), "conf/letsencrypt/user.key");
            }
            if (domainKey == null) {
                domainKey = new File(System.getProperty("catalina.base"), "conf/letsencrypt/domain.key");
            }
            if (domainCertificate == null) {
                domainCertificate = new File(System.getProperty("catalina.base"), "conf/letsencrypt/domain.csr");
            }
            if (domainChain == null) {
                domainChain = new File(System.getProperty("catalina.base"), "conf/letsencrypt/domain.chain.csr");
            }
            if (endpoint == null) {
                if (isStaging()) {
                    endpoint = "https://acme-staging-v02.api.letsencrypt.org/directory";
                } else {
                    endpoint = "https://acme-v02.api.letsencrypt.org/directory";
                }
            }
            Stream.of(userKeyLocation, domainKey, domainCertificate, domainChain).map(File::getAbsoluteFile)
                    .map(File::getParentFile).filter(Objects::nonNull).distinct().forEach(File::mkdirs);
        }

        public boolean isStaging() {
            return staging;
        }

        public int getRetryCount() {
            return retryCount;
        }

        public int getDomainKeySize() {
            return domainKeySize;
        }

        public String getEndpoint() {
            return endpoint;
        }

        public long getRefreshInterval() {
            return refreshInterval;
        }

        public String getDomains() {
            return domains;
        }

        public File getUserKeyLocation() {
            return userKeyLocation;
        }

        public int getUserKeySize() {
            return userKeySize;
        }

        public File getDomainKey() {
            return domainKey;
        }

        public File getDomainCertificate() {
            return domainCertificate;
        }

        public File getDomainChain() {
            return domainChain;
        }

        public long getRetryTimeoutMs() {
            return retryTimeoutMs;
        }
    }
}
