/*
 * 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.cassandra.sidecar.tasks;

import java.util.concurrent.TimeUnit;

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

import io.vertx.core.Promise;
import io.vertx.core.Vertx;
import org.apache.cassandra.sidecar.config.SslConfiguration;
import org.apache.cassandra.sidecar.server.Server;

/**
 * Periodically checks whether the key store file has changed. Triggers an update to the server's SSLOptions
 * whenever a file change has detected.
 */
public class KeyStoreCheckPeriodicTask implements PeriodicTask
{
    private static final Logger LOGGER = LoggerFactory.getLogger(KeyStoreCheckPeriodicTask.class);

    private final Vertx vertx;
    private final Server server;
    private final SslConfiguration configuration;
    private long lastModifiedTime = 0; // records the last modified timestamp

    public KeyStoreCheckPeriodicTask(Vertx vertx, Server server, SslConfiguration configuration)
    {
        this.vertx = vertx;
        this.server = server;
        this.configuration = configuration;
        maybeRecordLastModifiedTime();
    }

    /**
     * Skip check if the key store is not configured or if the key store should not be reloaded
     *
     * @return {@code true} if the key store is not configured or if the keystore should not be reloaded,
     * {@code false} otherwise
     */
    @Override
    public boolean shouldSkip()
    {
        return !configuration.isKeystoreConfigured()
               || !configuration.keystore().reloadStore();
    }

    @Override
    public long delay()
    {
        return configuration.keystore().checkIntervalInSeconds();
    }

    @Override
    public TimeUnit delayUnit()
    {
        return TimeUnit.SECONDS;
    }

    @Override
    public void execute(Promise<Void> promise)
    {
        LOGGER.info("Running periodic key store checker");
        String keyStorePath = configuration.keystore().path();
        vertx.fileSystem().props(keyStorePath)
             .onSuccess(props -> {
                 long previousLastModifiedTime = lastModifiedTime;
                 if (props.lastModifiedTime() != previousLastModifiedTime)
                 {
                     LOGGER.info("Certificate file change detected for path={}, previousLastModifiedTime={}, " +
                                 "lastModifiedTime={}", keyStorePath, previousLastModifiedTime,
                                 props.lastModifiedTime());

                     server.updateSSLOptions(props.lastModifiedTime())
                           .onSuccess(v -> {
                               lastModifiedTime = props.lastModifiedTime();
                               LOGGER.info("Completed reloading certificates from path={}", keyStorePath);
                               promise.complete(); // propagate successful completion
                           })
                           .onFailure(cause -> {
                               LOGGER.error("Failed to reload certificate from path={}", keyStorePath, cause);
                               promise.fail(cause);
                           });
                 }
                 else
                 {
                     promise.complete(); // make sure to fulfill the promise
                 }
             })
             .onFailure(error -> {
                 LOGGER.warn("Unable to retrieve props for path={}", keyStorePath, error);
                 promise.fail(error);
             });
    }

    protected void maybeRecordLastModifiedTime()
    {
        if (shouldSkip())
        {
            return;
        }
        String keyStorePath = configuration.keystore().path();
        vertx.fileSystem().props(keyStorePath)
             .onSuccess(props -> lastModifiedTime = props.lastModifiedTime())
             .onFailure(err -> {
                 LOGGER.error("Unable to get lastModifiedTime for path={}", keyStorePath);
                 lastModifiedTime = -1;
             });
    }
}
