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.datastax.driver.core.BatchStatement;

import org.apache.cassandra.stress.generate.DistributionFactory;
import org.apache.cassandra.stress.generate.RatioDistributionFactory;
import org.apache.cassandra.stress.util.ResultLogger;

public class SettingsInsert implements Serializable
{

    public final DistributionFactory revisit;
    public final DistributionFactory visits;
    public final DistributionFactory batchsize;
    public final RatioDistributionFactory selectRatio;
    public final RatioDistributionFactory rowPopulationRatio;
    public final BatchStatement.Type batchType;

    private SettingsInsert(InsertOptions options)
    {
        this.visits= options.visits.get();
        this.revisit = options.revisit.get();
        this.batchsize = options.partitions.get();
        this.selectRatio = options.selectRatio.get();
        this.rowPopulationRatio = options.rowPopulationRatio.get();



        this.batchType = !options.batchType.setByUser() ? null : BatchStatement.Type.valueOf(options.batchType.value());
    }

    // Option Declarations

    private static class InsertOptions extends GroupedOptions
    {
        final OptionDistribution visits = new OptionDistribution("visits=", "fixed(1)", "The target number of inserts to split a partition into; if more than one, the partition will be placed in the revisit set");
        final OptionDistribution revisit = new OptionDistribution("revisit=", "uniform(1..1M)", "The distribution with which we revisit partial writes (see visits); implicitly defines size of revisit collection");
        final OptionDistribution partitions = new OptionDistribution("partitions=", null, "The number of partitions to update in a single batch", false);
        final OptionSimple batchType = new OptionSimple("batchtype=", "unlogged|logged|counter", null, "Specify the type of batch statement (LOGGED, UNLOGGED or COUNTER)", false);
        final OptionRatioDistribution selectRatio = new OptionRatioDistribution("select-ratio=", null, "The uniform probability of visiting any CQL row in the generated partition", false);
        final OptionRatioDistribution rowPopulationRatio = new OptionRatioDistribution("row-population-ratio=", "fixed(1)/1", "The percent of a given rows columns to populate", false);

        @Override
        public List<? extends Option> options()
        {
            return Arrays.asList(revisit, visits, partitions, batchType, selectRatio, rowPopulationRatio);
        }
    }

    // CLI Utility Methods
    public void printSettings(ResultLogger out)
    {

        if (revisit != null)
        {
            out.println("  Revisits: " +revisit.getConfigAsString());
        }
        if (visits != null)
        {
            out.println("  Visits: " + visits.getConfigAsString());
        }
        if (batchsize != null)
        {
            out.println("  Batchsize: " +batchsize.getConfigAsString());
        }
        if (batchsize != null)
        {
            out.println("  Select Ratio: " +selectRatio.getConfigAsString());
        }
        if (rowPopulationRatio != null)
        {
            out.println("  Row Population Ratio: " +rowPopulationRatio.getConfigAsString());
        }
        if (batchType != null)
        {
            out.printf("  Batch Type: %s%n", batchType);
        } else {
            out.println("  Batch Type: not batching");
        }
    }


    public static SettingsInsert get(Map<String, String[]> clArgs)
    {
        String[] params = clArgs.remove("-insert");
        if (params == null)
            return new SettingsInsert(new InsertOptions());

        InsertOptions options = GroupedOptions.select(params, new InsertOptions());
        if (options == null)
        {
            printHelp();
            System.out.println("Invalid -insert options provided, see output for valid options");
            System.exit(1);
        }
        return new SettingsInsert(options);
    }

    public static void printHelp()
    {
        GroupedOptions.printOptions(System.out, "-insert", new InsertOptions());
    }

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

