package org.gnunet.statistics;

import org.gnunet.util.Program;
import org.gnunet.util.RelativeTime;
import org.gnunet.util.getopt.Argument;
import org.gnunet.util.getopt.ArgumentAction;


/**
 * Entry point for and implementation of the gnunet-statistics-java tool.
 */
public class StatisticsTool extends Program {
    @Argument(
            shortname = "x",
            longname = "set",
            action = ArgumentAction.SET,
            description = "set a value")
    boolean set;
    @Argument(
            shortname = "w",
            longname = "watch",
            action = ArgumentAction.SET,
            description = "watch a value")
    boolean watch;
    @Argument(
            shortname = "n",
            longname = "name",
            action = ArgumentAction.STORE_STRING,
            argumentName = "NAME",
            description = "statistics name")
    String statisticsName = "";
    @Argument(
            shortname = "s",
            longname = "subsystem",
            argumentName = "SUBSYS",
            action = ArgumentAction.STORE_STRING,
            description = "subsystem name")
    String subsystemName = "";
    @Argument(
            shortname = "p",
            longname = "persistent",
            action = ArgumentAction.SET,
            description = "set value persistently (used with -x)")
    boolean persistent = false;
    @Argument(
            shortname = "r",
            longname = "relative",
            action = ArgumentAction.SET,
            description = "set value relative to old value (used with -x)")
    boolean relative = false;

    /**
     * The handle to the statistics service.
     */
    Statistics statistics;

    /**
     * Statistics command line utility entry point
     *
     * @param args command line arguments
     */
    public static void main(String[] args) {
        StatisticsTool statisticsTool = new StatisticsTool();
        int ret = statisticsTool.start(args);
        System.exit(ret);
    }


    @Override
    protected String makeHelpText() {
        return "Get, set and watch GNUnet's statistics.";
    }

    public void run() {
        if (set && watch) {
            System.err.println("--watch/-w and --set/-s cannot be used together");
            return;
        }

        if (set) {
            if (subsystemName.isEmpty() || statisticsName.isEmpty()) {
                System.err.println("both subsystem and name must be given for --set/-x");
                return;
            }
            if (unprocessedArgs.length != 1) {
                System.err.println("must specify exactly one value to set");
                return;
            }
            long value;
            try {
                value = Long.parseLong(unprocessedArgs[0]);
            } catch (NumberFormatException e) {
                System.err.println("invalid value (not a long)");
                return;
            }
            statistics = new Statistics(cfg);
            if (relative)
                statistics.update(subsystemName, statisticsName, value, persistent);
            else
                statistics.set(subsystemName, statisticsName, value, persistent);
            statistics.destroy();
            return;
        }

        if (unprocessedArgs.length != 0) {
            System.err.println("watching or reading statistics does not take any positional parameters");
            return;
        }

        if (watch) {
            if (subsystemName.isEmpty() || statisticsName.isEmpty()) {
                System.err.println("both subsystem and name must be given for --watch/-w");
                return;
            }
            statistics = new Statistics(cfg);
            statistics.watch(subsystemName, statisticsName,
                    new StatisticsWatcher() {
                        @Override
                        public void onReceive(String subsystem, String name, long value) {
                            System.out.println(subsystem + "(" + name + ") = " + value);
                        }
                    }
            );
        } else {
            statistics = new Statistics(cfg);
            statistics.get(RelativeTime.fromSeconds(5), subsystemName, statisticsName,
                    new StatisticsReceiver() {
                        @Override
                        public void onReceive(String subsystem, String name, long value) {
                            System.out.println(subsystem + "(" + name + ") = " + value);
                        }

                        @Override
                        public void onTimeout() {
                            System.err.println("Statistics 'get' request timed out.");
                            statistics.destroy();
                        }

                        @Override
                        public void onDone() {
                            statistics.destroy();
                        }
                    }
            );
        }
    }
}
