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.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import org.apache.cassandra.stress.generate.DistributionFactory;
import org.apache.cassandra.stress.generate.PartitionGenerator;
import org.apache.cassandra.stress.generate.SeedManager;
import org.apache.cassandra.stress.generate.values.Bytes;
import org.apache.cassandra.stress.generate.values.Generator;
import org.apache.cassandra.stress.generate.values.GeneratorConfig;
import org.apache.cassandra.stress.generate.values.HexBytes;
import org.apache.cassandra.stress.operations.FixedOpDistribution;
import org.apache.cassandra.stress.operations.OpDistribution;
import org.apache.cassandra.stress.operations.OpDistributionFactory;
import org.apache.cassandra.stress.operations.predefined.PredefinedOperation;
import org.apache.cassandra.stress.util.Timing;

// Settings unique to the mixed command type
public class SettingsCommandPreDefined extends SettingsCommand
{

    public final DistributionFactory add;
    public final int keySize;

    public OpDistributionFactory getFactory(final StressSettings settings)
    {
        final SeedManager seeds = new SeedManager(settings);
        return new OpDistributionFactory()
        {
            public OpDistribution get(Timing timing, boolean isWarmup)
            {
                return new FixedOpDistribution(PredefinedOperation.operation(type, timing.newTimer(type.toString()),
                                               newGenerator(settings), seeds, settings, add));
            }

            public String desc()
            {
                return type.toString();
            }

            public Iterable<OpDistributionFactory> each()
            {
                return Collections.<OpDistributionFactory>singleton(this);
            }
        };
    }

    PartitionGenerator newGenerator(StressSettings settings)
    {
        List<String> names = settings.columns.namestrs;
        List<Generator> partitionKey = Collections.<Generator>singletonList(new HexBytes("key",
                                       new GeneratorConfig("randomstrkey", null,
                                                           OptionDistribution.get("fixed(" + keySize + ")"), null)));

        List<Generator> columns = new ArrayList<>();
        for (int i = 0 ; i < settings.columns.maxColumnsPerKey ; i++)
            columns.add(new Bytes(names.get(i), new GeneratorConfig("randomstr" + names.get(i), null, settings.columns.sizeDistribution, null)));
        return new PartitionGenerator(partitionKey, Collections.<Generator>emptyList(), columns, PartitionGenerator.Order.ARBITRARY);
    }

    public SettingsCommandPreDefined(Command type, Options options)
    {
        super(type, options.parent);
        add = options.add.get();
        keySize = Integer.parseInt(options.keysize.value());
    }

    // Option Declarations

    static class Options extends GroupedOptions
    {
        final SettingsCommand.Options parent;
        protected Options(SettingsCommand.Options parent)
        {
            this.parent = parent;
        }
        final OptionDistribution add = new OptionDistribution("add=", "fixed(1)", "Distribution of value of counter increments");
        final OptionSimple keysize = new OptionSimple("keysize=", "[0-9]+", "10", "Key size in bytes", false);

        @Override
        public List<? extends Option> options()
        {
            return merge(parent.options(), Arrays.asList(add, keysize));
        }

    }

    public void truncateTables(StressSettings settings)
    {
        truncateTables(settings, settings.schema.keyspace, "standard1", "counter1", "counter3");
    }

    // CLI utility methods

    public static SettingsCommandPreDefined build(Command type, String[] params)
    {
        GroupedOptions options = GroupedOptions.select(params,
                new Options(new Uncertainty()),
                new Options(new Count()),
                new Options(new Duration()));
        if (options == null)
        {
            printHelp(type);
            System.out.println("Invalid " + type + " options provided, see output for valid options");
            System.exit(1);
        }
        return new SettingsCommandPreDefined(type, (Options) options);
    }

    static void printHelp(Command type)
    {
        printHelp(type.toString().toLowerCase());
    }

    static void printHelp(String type)
    {
        GroupedOptions.printOptions(System.out, type.toLowerCase(), new Uncertainty(), new Count(), new Duration());
    }

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