package org.apache.cassandra.stress.settings;
/*
 * 
 * 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.
 * 
 */


import java.io.Serializable;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import com.google.common.collect.ImmutableList;

import org.apache.cassandra.stress.generate.DistributionFactory;
import org.apache.cassandra.stress.generate.PartitionGenerator;

public class SettingsPopulation implements Serializable
{

    public final DistributionFactory distribution;
    public final DistributionFactory readlookback;
    public final PartitionGenerator.Order order;
    public final boolean wrap;
    public final long[] sequence;

    public static enum GenerateOrder
    {
        ARBITRARY, SHUFFLED, SORTED
    }

    private SettingsPopulation(GenerateOptions options, DistributionOptions dist, SequentialOptions pop)
    {
        this.order = !options.contents.setByUser() ? PartitionGenerator.Order.ARBITRARY : PartitionGenerator.Order.valueOf(options.contents.value().toUpperCase());
        if (dist != null)
        {
            this.distribution = dist.seed.get();
            this.sequence = null;
            this.readlookback = null;
            this.wrap = false;
        }
        else
        {
            this.distribution = null;
            String[] bounds = pop.populate.value().split("\\.\\.+");
            this.sequence = new long[] { OptionDistribution.parseLong(bounds[0]), OptionDistribution.parseLong(bounds[1]) };
            this.readlookback = pop.lookback.get();
            this.wrap = !pop.nowrap.setByUser();
        }
    }

    public SettingsPopulation(DistributionOptions options)
    {
        this(options, options, null);
    }

    public SettingsPopulation(SequentialOptions options)
    {
        this(options, null, options);
    }

    // Option Declarations

    private static class GenerateOptions extends GroupedOptions
    {
        final OptionSimple contents = new OptionSimple("contents=", "(sorted|shuffled)", null, "SORTED or SHUFFLED (intra-)partition order; if not specified, will be consistent but arbitrary order", false);

        @Override
        public List<? extends Option> options()
        {
            return Arrays.asList(contents);
        }
    }

    private static final class DistributionOptions extends GenerateOptions
    {
        final OptionDistribution seed;

        public DistributionOptions(String defaultLimit)
        {
            seed = new OptionDistribution("dist=", "gaussian(1.." + defaultLimit + ")", "Seeds are selected from this distribution");
        }

        @Override
        public List<? extends Option> options()
        {
            return ImmutableList.<Option>builder().add(seed).addAll(super.options()).build();
        }
    }

    private static final class SequentialOptions extends GenerateOptions
    {
        final OptionSimple populate;
        final OptionDistribution lookback = new OptionDistribution("read-lookback=", null, "Select read seeds from the recently visited write seeds", false);
        final OptionSimple nowrap = new OptionSimple("no-wrap", "", null, "Terminate the stress test once all seeds in the range have been visited", false);

        public SequentialOptions(String defaultLimit)
        {
            populate = new OptionSimple("seq=", "[0-9]+[MBK]?\\.\\.+[0-9]+[MBK]?",
                    "1.." + defaultLimit,
                    "Generate all seeds in sequence", true);
        }

        @Override
        public List<? extends Option> options()
        {
            return ImmutableList.<Option>builder().add(populate, nowrap, lookback).addAll(super.options()).build();
        }
    }

    // CLI Utility Methods

    public static SettingsPopulation get(Map<String, String[]> clArgs, SettingsCommand command)
    {
        // set default size to number of commands requested, unless set to err convergence, then use 1M
        String defaultLimit = command.count <= 0 ? "1000000" : Long.toString(command.count);

        String[] params = clArgs.remove("-pop");
        if (params == null)
        {
            if (command instanceof SettingsCommandUser && ((SettingsCommandUser)command).hasInsertOnly())
            {
                return new SettingsPopulation(new SequentialOptions(defaultLimit));
            }

            // return defaults:
            switch(command.type)
            {
                case WRITE:
                case COUNTER_WRITE:
                    return new SettingsPopulation(new SequentialOptions(defaultLimit));
                default:
                    return new SettingsPopulation(new DistributionOptions(defaultLimit));
            }
        }
        GroupedOptions options = GroupedOptions.select(params, new SequentialOptions(defaultLimit), new DistributionOptions(defaultLimit));
        if (options == null)
        {
            printHelp();
            System.out.println("Invalid -pop options provided, see output for valid options");
            System.exit(1);
        }
        return options instanceof SequentialOptions ?
                new SettingsPopulation((SequentialOptions) options) :
                new SettingsPopulation((DistributionOptions) options);
    }

    public static void printHelp()
    {
        GroupedOptions.printOptions(System.out, "-pop", new SequentialOptions("N"), new DistributionOptions("N"));
    }

    public static Runnable helpPrinter()
    {
        return new Runnable()
        {
            @Override
            public void run()
            {
                printHelp();
            }
        };
    }
}

