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

import java.io.File;
import java.net.MalformedURLException;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.OptionGroup;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.PosixParser;
import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.IgniteState;
import org.apache.ignite.IgniteSystemProperties;
import org.apache.ignite.IgnitionListener;
import org.apache.ignite.configuration.IgniteConfiguration;
import org.apache.ignite.internal.IgniteVersionUtils;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.internal.util.typedef.G;
import org.apache.ignite.internal.util.typedef.internal.U;
import org.apache.ignite.testframework.GridTestUtils;
import org.apache.ignite.testframework.junits.logger.GridTestLog4jLogger;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

import static org.apache.ignite.IgniteState.STOPPED;

/**
 * This class defines random command-line Ignite loader. This loader can be used
 * to randomly start and stop Ignite from command line for tests. This loader is a Java
 * application with {@link #main(String[])} method that accepts command line arguments.
 * See below for details.
 */
public final class GridRandomCommandLineLoader {
    /** Name of the system property defining name of command line program. */
    private static final String IGNITE_PROG_NAME = "IGNITE_PROG_NAME";

    /** Copyright text. Ant processed. */
    private static final String COPYRIGHT = IgniteVersionUtils.COPYRIGHT;

    /** Version. Ant processed. */
    private static final String VER = "x.x.x";

    /** */
    private static final String OPTION_HELP = "help";

    /** */
    private static final String OPTION_CFG = "cfg";

    /** */
    private static final String OPTION_MIN_TTL = "minTtl";

    /** */
    private static final String OPTION_MAX_TTL = "maxTtl";

    /** */
    private static final String OPTION_DURATION = "duration";

    /** */
    private static final String OPTION_LOG_CFG = "logCfg";

    /** Minimal value for timeout in milliseconds. */
    private static final long DFLT_MIN_TIMEOUT = 1000;

    /** Maximum value for timeout in milliseconds. */
    private static final long DFLT_MAX_TIMEOUT = 1000 * 20;

    /** Work timeout in milliseconds. */
    private static final long DFLT_RUN_TIMEOUT = 1000 * 60 * 5;

    /** Latch. */
    private static CountDownLatch latch;

    /**
     * Enforces singleton.
     */
    private GridRandomCommandLineLoader() {
        // No-op.
    }

    /**
     * Echos the given messages.
     *
     * @param msg Message to echo.
     */
    private static void echo(String msg) {
        assert msg != null;

        System.out.println(msg);
    }

    /**
     * Echos exception stack trace.
     *
     * @param e Exception to print.
     */
    private static void echo(IgniteCheckedException e) {
        assert e != null;

        System.err.println(e);
    }

    /**
     * Exists with optional error message, usage show and exit code.
     *
     * @param errMsg Optional error message.
     * @param options Command line options to show usage information.
     * @param exitCode Exit code.
     */
    private static void exit(@Nullable String errMsg, @Nullable Options options, int exitCode) {
        if (errMsg != null)
            echo("ERROR: " + errMsg);

        String runner = System.getProperty(IGNITE_PROG_NAME, "randignite.{sh|bat}");

        int space = runner.indexOf(' ');

        runner = runner.substring(0, space == -1 ? runner.length() : space);

        if (options != null) {
            HelpFormatter formatter = new HelpFormatter();

            formatter.printHelp(runner, options);
        }

        System.exit(exitCode);
    }

    /**
     * Prints logo.
     */
    private static void logo() {
        echo("Ignite Random Command Line Loader, ver. " + VER);
        echo(COPYRIGHT);
        echo("");
    }

    /**
     * Main entry point.
     *
     * @param args Command line arguments.
     */
    @SuppressWarnings({"BusyWait"})
    public static void main(String[] args) {
        System.setProperty(IgniteSystemProperties.IGNITE_UPDATE_NOTIFIER, "false");

        logo();

        Options options = createOptions();

        // Create the command line parser.
        CommandLineParser parser = new PosixParser();

        String cfgPath = null;

        long minTtl = DFLT_MIN_TIMEOUT;
        long maxTtl = DFLT_MAX_TIMEOUT;
        long duration = DFLT_RUN_TIMEOUT;

        String logCfgPath = null;

        try {
            CommandLine cmd = parser.parse(options, args);

            if (cmd.hasOption(OPTION_HELP))
                exit(null, options, 0);

            if (!cmd.hasOption(OPTION_LOG_CFG))
                exit("-log should be set", options, -1);
            else
                logCfgPath = cmd.getOptionValue(OPTION_LOG_CFG);

            if (cmd.hasOption(OPTION_CFG))
                cfgPath = cmd.getOptionValue(OPTION_CFG);

            try {
                if (cmd.hasOption(OPTION_DURATION))
                    duration = Long.parseLong(cmd.getOptionValue(OPTION_DURATION));
            }
            catch (NumberFormatException ignored) {
                exit("Invalid argument for option: " + OPTION_DURATION, options, -1);
            }

            try {
                if (cmd.hasOption(OPTION_MIN_TTL))
                    minTtl = Long.parseLong(cmd.getOptionValue(OPTION_MIN_TTL));
            }
            catch (NumberFormatException ignored) {
                exit("Invalid argument for option: " + OPTION_MIN_TTL, options, -1);
            }

            try {
                if (cmd.hasOption(OPTION_MAX_TTL))
                    maxTtl = Long.parseLong(cmd.getOptionValue(OPTION_MAX_TTL));
            }
            catch (NumberFormatException ignored) {
                exit("Invalid argument for option: " + OPTION_MAX_TTL, options, -1);
            }

            if (minTtl >= maxTtl)
                exit("Invalid arguments for options: " + OPTION_MAX_TTL + ", " + OPTION_MIN_TTL, options, -1);
        }
        catch (ParseException e) {
            exit(e.getMessage(), options, -1);
        }

        System.out.println("Configuration path: " + cfgPath);
        System.out.println("Log4j configuration path: " + logCfgPath);
        System.out.println("Duration: " + duration);
        System.out.println("Minimum TTL: " + minTtl);
        System.out.println("Maximum TTL: " + maxTtl);

        G.addListener(new IgnitionListener() {
            @Override public void onStateChange(String name, IgniteState state) {
                if (state == STOPPED && latch != null)
                    latch.countDown();
            }
        });

        Random rand = new Random();

        long now = System.currentTimeMillis();

        long end = duration + System.currentTimeMillis();

        try {
            while (now < end) {
                G.start(getConfiguration(cfgPath, logCfgPath));

                long delay = rand.nextInt((int)(maxTtl - minTtl)) + minTtl;

                delay = (now + delay > end) ? (end - now) : delay;

                now = System.currentTimeMillis();

                echo("Time left (ms): " + (end - now));

                echo("Going to sleep for (ms): " + delay);

                Thread.sleep(delay);

                G.stopAll(false);

                now = System.currentTimeMillis();
            }
        }
        catch (IgniteCheckedException e) {
            echo(e);

            exit("Failed to start grid: " + e.getMessage(), null, -1);
        }
        catch (InterruptedException e) {
            echo("Loader was interrupted (exiting): " + e.getMessage());
        }

        latch = new CountDownLatch(G.allGrids().size());

        try {
            while (latch.getCount() > 0)
                latch.await();
        }
        catch (InterruptedException e) {
            echo("Loader was interrupted (exiting): " + e.getMessage());
        }

        System.exit(0);
    }

    /**
     * Initializes configurations.
     *
     * @param springCfgPath Configuration file path.
     * @param logCfgPath Log file name.
     * @return List of configurations.
     * @throws IgniteCheckedException If an error occurs.
     */
    private static IgniteConfiguration getConfiguration(String springCfgPath, @Nullable String logCfgPath)
        throws IgniteCheckedException {
        assert springCfgPath != null;

        File path = GridTestUtils.resolveIgnitePath(springCfgPath);

        if (path == null)
            throw new IgniteCheckedException("Spring XML configuration file path is invalid: " + new File(springCfgPath) +
                ". Note that this path should be either absolute path or a relative path to IGNITE_HOME.");

        if (!path.isFile())
            throw new IgniteCheckedException("Provided file path is not a file: " + path);

        ApplicationContext springCtx;

        try {
            springCtx = new FileSystemXmlApplicationContext(path.toURI().toURL().toString());
        }
        catch (BeansException | MalformedURLException e) {
            throw new IgniteCheckedException("Failed to instantiate Spring XML application context: " + e.getMessage(), e);
        }

        Map cfgMap;

        try {
            // Note: Spring is not generics-friendly.
            cfgMap = springCtx.getBeansOfType(IgniteConfiguration.class);
        }
        catch (BeansException e) {
            throw new IgniteCheckedException("Failed to instantiate bean [type=" + IgniteConfiguration.class + ", err=" +
                e.getMessage() + ']', e);
        }

        if (cfgMap == null)
            throw new IgniteCheckedException("Failed to find a single grid factory configuration in: " + path);

        if (cfgMap.size() != 1)
            throw new IgniteCheckedException("Spring configuration file should contain exactly 1 grid configuration: " + path);

        IgniteConfiguration cfg = (IgniteConfiguration)F.first(cfgMap.values());

        assert cfg != null;

        if (logCfgPath != null)
            cfg.setGridLogger(new GridTestLog4jLogger(U.resolveIgniteUrl(logCfgPath)));

        return cfg;
    }

    /**
     * Creates cli options.
     *
     * @return Command line options
     */
    private static Options createOptions() {
        Options options = new Options();

        Option help = new Option(OPTION_HELP, "print this message");

        Option cfg = new Option(null, OPTION_CFG, true, "path to Spring XML configuration file.");

        cfg.setValueSeparator('=');
        cfg.setType(String.class);

        Option minTtl = new Option(null, OPTION_MIN_TTL, true, "node minimum time to live.");

        minTtl.setValueSeparator('=');
        minTtl.setType(Long.class);

        Option maxTtl = new Option(null, OPTION_MAX_TTL, true, "node maximum time to live.");

        maxTtl.setValueSeparator('=');
        maxTtl.setType(Long.class);

        Option duration = new Option(null, OPTION_DURATION, true, "run timeout.");

        duration.setValueSeparator('=');
        duration.setType(Long.class);

        Option log = new Option(null, OPTION_LOG_CFG, true, "path to log4j configuration file.");

        log.setValueSeparator('=');
        log.setType(String.class);

        options.addOption(help);

        OptionGroup grp = new OptionGroup();

        grp.setRequired(true);

        grp.addOption(cfg);
        grp.addOption(minTtl);
        grp.addOption(maxTtl);
        grp.addOption(duration);
        grp.addOption(log);

        options.addOptionGroup(grp);

        return options;
    }
}
