/*
 * 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.ignite.internal.testframework;

import static java.nio.file.StandardOpenOption.CREATE;
import static java.nio.file.StandardOpenOption.SYNC;
import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING;
import static org.apache.ignite.internal.util.Constants.MiB;

import com.typesafe.config.ConfigException;
import com.typesafe.config.parser.ConfigDocument;
import com.typesafe.config.parser.ConfigDocumentFactory;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import org.apache.ignite.Ignite;
import org.apache.ignite.IgnitionManager;
import org.apache.ignite.InitParameters;
import org.apache.ignite.InitParametersBuilder;
import org.apache.ignite.internal.hlc.TestClockService;
import org.apache.ignite.lang.IgniteException;
import org.jetbrains.annotations.Nullable;

/** Helper class for starting a node with a string-based configuration. */
public class TestIgnitionManager {

    /** Default name of configuration file. */
    public static final String DEFAULT_CONFIG_NAME = "ignite-config.conf";

    private static final int DEFAULT_SCALECUBE_METADATA_TIMEOUT = 10_000;

    /** Default DelayDuration in ms used for tests that is set on node init. */
    public static final int DEFAULT_DELAY_DURATION_MS = 100;

    private static final int DEFAULT_METASTORAGE_IDLE_SYNC_TIME_INTERVAL_MS = 10;

    /** Default partition idle SafeTime interval in ms used for tests that is set on node init. */
    public static final int DEFAULT_PARTITION_IDLE_SYNC_TIME_INTERVAL_MS = 100;

    public static final long DEFAULT_MAX_CLOCK_SKEW_MS = TestClockService.TEST_MAX_CLOCK_SKEW_MILLIS;

    /** Map with default node configuration values. */
    private static final Map<String, String> DEFAULT_NODE_CONFIG = Map.of(
            "network.membership.scaleCube.metadataTimeout", Integer.toString(DEFAULT_SCALECUBE_METADATA_TIMEOUT),
            "storage.profiles.default_aipersist.engine", "aipersist",
            "storage.profiles.default_aipersist.size", Integer.toString(256 * MiB),
            "storage.profiles.default_aimem.engine", "aimem",
            "storage.profiles.default_aimem.initSize", Integer.toString(256 * MiB),
            "storage.profiles.default_aimem.maxSize", Integer.toString(256 * MiB),
            "storage.profiles.default.engine", "aipersist"
    );

    /** Map with default cluster configuration values. */
    private static final Map<String, String> DEFAULT_CLUSTER_CONFIG = Map.of(
            "schemaSync.delayDuration", Integer.toString(DEFAULT_DELAY_DURATION_MS),
            "schemaSync.maxClockSkew", Long.toString(DEFAULT_MAX_CLOCK_SKEW_MS),
            "metaStorage.idleSyncTimeInterval", Integer.toString(DEFAULT_METASTORAGE_IDLE_SYNC_TIME_INTERVAL_MS),
            "replication.idleSafeTimePropagationDuration", Integer.toString(DEFAULT_PARTITION_IDLE_SYNC_TIME_INTERVAL_MS)
    );

    /**
     * Marker that explicitly requests production defaults when put to {@link InitParametersBuilder#clusterConfiguration(String)}.
     */
    public static final String PRODUCTION_CLUSTER_CONFIG_STRING = "<production-cluster-config>";

    /**
     * Starts an Ignite node with an optional bootstrap configuration from an input stream with HOCON configs.
     *
     * <p>Test defaults are mixed to the configuration (only if the corresponding config keys are not explicitly defined).
     *
     * <p>When this method returns, the node is partially started and ready to accept the init command (that is, its
     * REST endpoint is functional).
     *
     * @param nodeName Name of the node. Must not be {@code null}.
     * @param configStr Optional node configuration.
     *      Following rules are used for applying the configuration properties:
     *      <ol>
     *        <li>Specified property overrides existing one or just applies itself if it wasn't
     *            previously specified.</li>
     *        <li>All non-specified properties either use previous value or use default one from
     *            corresponding configuration schema.</li>
     *      </ol>
     *      So that, in case of initial node start (first start ever) specified configuration, supplemented
     *      with defaults, is used. If no configuration was provided defaults are used for all
     *      configuration properties. In case of node restart, specified properties override existing
     *      ones, non specified properties that also weren't specified previously use default values.
     *      Please pay attention that previously specified properties are searched in the
     *      {@code workDir} specified by the user.
     *
     * @param workDir Work directory for the started node. Must not be {@code null}.
     * @return Completable future that resolves into an Ignite node after all components are started and the cluster initialization is
     *         complete.
     * @throws IgniteException If error occurs while reading node configuration.
     */
    public static CompletableFuture<Ignite> start(String nodeName, @Nullable String configStr, Path workDir) {
        try {
            Files.createDirectories(workDir);
            Path configPath = workDir.resolve(DEFAULT_CONFIG_NAME);

            addDefaultsToConfigurationFile(configStr, configPath);

            return IgnitionManager.start(nodeName, configPath, workDir);
        } catch (IOException e) {
            throw new IgniteException("Couldn't write node config.", e);
        }
    }

    /**
     * Writes default values into the configuration file, according to the same rules that are used in {@link #start(String, String, Path)}.
     */
    public static void addDefaultsToConfigurationFile(Path configPath) {
        try {
            addDefaultsToConfigurationFile(null, configPath);
        } catch (IOException e) {
            throw new IgniteException("Couldn't update node configuration file", e);
        }
    }

    private static void addDefaultsToConfigurationFile(@Nullable String configStr, Path configPath) throws IOException {
        if (configStr == null && Files.exists(configPath)) {
            // Nothing to do.
            return;
        }

        Files.writeString(configPath, applyTestDefaultsToConfig(configStr, DEFAULT_NODE_CONFIG), SYNC, CREATE, TRUNCATE_EXISTING);
    }

    /**
     * Initializes a cluster using test defaults for cluster configuration values that are not
     * specified explicitly.
     *
     * @param parameters Init parameters.
     * @see IgnitionManager#init(InitParameters)
     */
    public static void init(InitParameters parameters) {
        IgnitionManager.init(applyTestDefaultsToClusterConfig(parameters));
    }

    private static InitParameters applyTestDefaultsToClusterConfig(InitParameters params) {
        InitParametersBuilder builder = new InitParametersBuilder()
                .clusterName(params.clusterName())
                .destinationNodeName(params.nodeName())
                .metaStorageNodeNames(params.metaStorageNodeNames())
                .cmgNodeNames(params.cmgNodeNames());

        if (!PRODUCTION_CLUSTER_CONFIG_STRING.equals(params.clusterConfiguration())) {
            builder.clusterConfiguration(applyTestDefaultsToConfig(params.clusterConfiguration(), DEFAULT_CLUSTER_CONFIG));
        }

        return builder.build();
    }

    private static String applyTestDefaultsToConfig(@Nullable String configStr, Map<String, String> defaults) {
        if (configStr == null) {
            configStr = "{}";
        }

        ConfigDocument configDocument;

        try {
            configDocument = ConfigDocumentFactory.parseString(configStr);
        } catch (ConfigException e) {
            // Preserve original broken content, it might be broken on purpose.
            return configStr;
        }

        for (Entry<String, String> entry : defaults.entrySet()) {
            configDocument = applyTestDefault(
                    configDocument,
                    entry.getKey(),
                    entry.getValue()
            );
        }

        return configDocument.render();
    }

    private static ConfigDocument parseNullableConfigString(@Nullable String configString) {
        String configToParse = Objects.requireNonNullElse(configString, "{}");

        return ConfigDocumentFactory.parseString(configToParse);
    }

    private static ConfigDocument applyTestDefault(ConfigDocument document, String path, String value) {
        if (document.hasPath(path)) {
            return document;
        } else {
            return document.withValueText(path, value);
        }
    }
}
