/*
 * 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.accumulo.testing.randomwalk.concurrent;

import java.util.Properties;
import java.util.SortedSet;

import org.apache.accumulo.core.client.AccumuloException;
import org.apache.accumulo.core.clientImpl.thrift.TableOperationExceptionType;
import org.apache.accumulo.core.clientImpl.thrift.ThriftTableOperationException;
import org.apache.accumulo.core.conf.Property;
import org.apache.accumulo.testing.randomwalk.RandWalkEnv;
import org.apache.accumulo.testing.randomwalk.State;
import org.apache.accumulo.testing.randomwalk.Test;
import org.apache.commons.math3.random.RandomDataGenerator;

public class Config extends Test {

  private static final String LAST_SETTING = "lastSetting";

  private static final String LAST_TABLE_SETTING = "lastTableSetting";

  private static final String LAST_NAMESPACE_SETTING = "lastNamespaceSetting";

  static class Setting {
    public Property property;
    public long min;
    public long max;

    public Setting(Property property, long min, long max) {
      this.property = property;
      this.min = min;
      this.max = max;
    }
  }

  static Setting s(Property property, long min, long max) {
    return new Setting(property, min, max);
  }

  // @formatter:off
	Setting[] settings = {
			s(Property.TSERV_BLOOM_LOAD_MAXCONCURRENT, 1, 10),
			s(Property.TSERV_BULK_PROCESS_THREADS, 1, 10),
			s(Property.TSERV_BULK_RETRY, 1, 10),
			s(Property.TSERV_BULK_TIMEOUT, 10, 600),
			s(Property.TSERV_BULK_ASSIGNMENT_THREADS, 1, 10),
			s(Property.TSERV_DATACACHE_SIZE, 0, 1000000000L),
			s(Property.TSERV_INDEXCACHE_SIZE, 0, 1000000000L),
			s(Property.TSERV_CLIENT_TIMEOUT, 100, 10000),
			s(Property.TSERV_MAJC_MAXCONCURRENT, 1, 10),
			s(Property.TSERV_MAJC_DELAY, 100, 10000),
			s(Property.TSERV_MAJC_THREAD_MAXOPEN, 3, 100),
			s(Property.TSERV_MINC_MAXCONCURRENT, 1, 10),
			s(Property.TSERV_DEFAULT_BLOCKSIZE, 100000, 10000000L),
			s(Property.TSERV_MAX_IDLE, 10000, 500 * 1000),
			s(Property.TSERV_MAXMEM, 1000000, 3 * 1024 * 1024 * 1024L),
			s(Property.TSERV_READ_AHEAD_MAXCONCURRENT, 1, 25),
			s(Property.TSERV_MIGRATE_MAXCONCURRENT, 1, 10),
			s(Property.TSERV_TOTAL_MUTATION_QUEUE_MAX, 10000, 1024 * 1024),
			s(Property.TSERV_RECOVERY_MAX_CONCURRENT, 1, 100),
			s(Property.TSERV_SCAN_MAX_OPENFILES, 10, 1000),
			s(Property.TSERV_THREADCHECK, 100, 10000),
			s(Property.TSERV_MINTHREADS, 1, 100),
			s(Property.TSERV_SESSION_MAXIDLE, 100, 5 * 60 * 1000),
			s(Property.TSERV_SORT_BUFFER_SIZE, 1024 * 1024, 1024 * 1024 * 1024L),
			s(Property.TSERV_TABLET_SPLIT_FINDMIDPOINT_MAXOPEN, 5, 100),
			s(Property.TSERV_WAL_BLOCKSIZE, 1024 * 1024,
					1024 * 1024 * 1024 * 10L),
			s(Property.TSERV_WORKQ_THREADS, 1, 10),
			s(Property.MASTER_BULK_THREADPOOL_SIZE, 1, 10),
			s(Property.MASTER_BULK_RETRIES, 1, 10),
			s(Property.MASTER_BULK_TIMEOUT, 10, 600),
			s(Property.MASTER_FATE_THREADPOOL_SIZE, 1, 100),
			s(Property.MASTER_RECOVERY_DELAY, 0, 100),
			s(Property.MASTER_LEASE_RECOVERY_WAITING_PERIOD, 0, 10),
			s(Property.MASTER_THREADCHECK, 100, 10000),
			s(Property.MASTER_MINTHREADS, 1, 200),};

	Setting[] tableSettings = {
			s(Property.TABLE_MAJC_RATIO, 1, 10),
			s(Property.TABLE_MAJC_COMPACTALL_IDLETIME, 100,
					10 * 60 * 60 * 1000L),
			s(Property.TABLE_SPLIT_THRESHOLD, 10 * 1024,
					10L * 1024 * 1024 * 1024),
			s(Property.TABLE_MINC_COMPACT_IDLETIME, 100, 100 * 60 * 60 * 1000L),
			s(Property.TABLE_SCAN_MAXMEM, 10 * 1024, 10 * 1024 * 1024),
			s(Property.TABLE_FILE_COMPRESSED_BLOCK_SIZE, 10 * 1024,
					10 * 1024 * 1024L),
			s(Property.TABLE_FILE_COMPRESSED_BLOCK_SIZE_INDEX, 10 * 1024,
					10 * 1024 * 1024L),
			s(Property.TABLE_FILE_REPLICATION, 0, 5),
			s(Property.TABLE_FILE_MAX, 2, 50),};
	// @formatter:on

  @Override
  public void visit(State state, RandWalkEnv env, Properties props) throws Exception {
    // reset any previous setting
    Object lastSetting = state.getOkIfAbsent(LAST_SETTING);
    if (lastSetting != null) {
      int choice = Integer.parseInt(lastSetting.toString());
      Property property = settings[choice].property;
      log.debug("Setting " + property.getKey() + " back to " + property.getDefaultValue());
      env.getAccumuloClient().instanceOperations().setProperty(property.getKey(), property.getDefaultValue());
    }
    lastSetting = state.getOkIfAbsent(LAST_TABLE_SETTING);
    if (lastSetting != null) {
      String parts[] = lastSetting.toString().split(",");
      String table = parts[0];
      int choice = Integer.parseInt(parts[1]);
      Property property = tableSettings[choice].property;
      if (env.getAccumuloClient().tableOperations().exists(table)) {
        log.debug("Setting " + property.getKey() + " on " + table + " back to " + property.getDefaultValue());
        try {
          env.getAccumuloClient().tableOperations().setProperty(table, property.getKey(), property.getDefaultValue());
        } catch (AccumuloException ex) {
          if (ex.getCause() instanceof ThriftTableOperationException) {
            ThriftTableOperationException ttoe = (ThriftTableOperationException) ex.getCause();
            if (ttoe.type == TableOperationExceptionType.NOTFOUND)
              return;
          }
          throw ex;
        }
      }
    }
    lastSetting = state.getOkIfAbsent(LAST_NAMESPACE_SETTING);
    if (lastSetting != null) {
      String parts[] = lastSetting.toString().split(",");
      String namespace = parts[0];
      int choice = Integer.parseInt(parts[1]);
      Property property = tableSettings[choice].property;
      if (env.getAccumuloClient().namespaceOperations().exists(namespace)) {
        log.debug("Setting " + property.getKey() + " on " + namespace + " back to " + property.getDefaultValue());
        try {
          env.getAccumuloClient().namespaceOperations().setProperty(namespace, property.getKey(), property.getDefaultValue());
        } catch (AccumuloException ex) {
          if (ex.getCause() instanceof ThriftTableOperationException) {
            ThriftTableOperationException ttoe = (ThriftTableOperationException) ex.getCause();
            if (ttoe.type == TableOperationExceptionType.NAMESPACE_NOTFOUND)
              return;
          }
          throw ex;
        }
      }
    }
    state.remove(LAST_SETTING);
    state.remove(LAST_TABLE_SETTING);
    state.remove(LAST_NAMESPACE_SETTING);
    RandomDataGenerator random = new RandomDataGenerator();
    int dice = random.nextInt(0, 2);
    if (dice == 0) {
      changeTableSetting(random, state, env, props);
    } else if (dice == 1) {
      changeNamespaceSetting(random, state, env, props);
    } else {
      changeSetting(random, state, env, props);
    }
  }

  private void changeTableSetting(RandomDataGenerator random, State state, RandWalkEnv env, Properties props) throws Exception {
    // pick a random property
    int choice = random.nextInt(0, tableSettings.length - 1);
    Setting setting = tableSettings[choice];

    // pick a random table
    SortedSet<String> tables = env.getAccumuloClient().tableOperations().list().tailSet("ctt").headSet("ctu");
    if (tables.isEmpty())
      return;
    String table = random.nextSample(tables, 1)[0].toString();

    // generate a random value
    long newValue = random.nextLong(setting.min, setting.max);
    state.set(LAST_TABLE_SETTING, table + "," + choice);
    log.debug("Setting " + setting.property.getKey() + " on table " + table + " to " + newValue);
    try {
      env.getAccumuloClient().tableOperations().setProperty(table, setting.property.getKey(), "" + newValue);
    } catch (AccumuloException ex) {
      if (ex.getCause() instanceof ThriftTableOperationException) {
        ThriftTableOperationException ttoe = (ThriftTableOperationException) ex.getCause();
        if (ttoe.type == TableOperationExceptionType.NOTFOUND)
          return;
      }
      throw ex;
    }
  }

  private void changeNamespaceSetting(RandomDataGenerator random, State state, RandWalkEnv env, Properties props) throws Exception {
    // pick a random property
    int choice = random.nextInt(0, tableSettings.length - 1);
    Setting setting = tableSettings[choice];

    // pick a random table
    SortedSet<String> namespaces = env.getAccumuloClient().namespaceOperations().list().tailSet("nspc").headSet("nspd");
    if (namespaces.isEmpty())
      return;
    String namespace = random.nextSample(namespaces, 1)[0].toString();

    // generate a random value
    long newValue = random.nextLong(setting.min, setting.max);
    state.set(LAST_NAMESPACE_SETTING, namespace + "," + choice);
    log.debug("Setting " + setting.property.getKey() + " on namespace " + namespace + " to " + newValue);
    try {
      env.getAccumuloClient().namespaceOperations().setProperty(namespace, setting.property.getKey(), "" + newValue);
    } catch (AccumuloException ex) {
      if (ex.getCause() instanceof ThriftTableOperationException) {
        ThriftTableOperationException ttoe = (ThriftTableOperationException) ex.getCause();
        if (ttoe.type == TableOperationExceptionType.NAMESPACE_NOTFOUND)
          return;
      }
      throw ex;
    }
  }

  private void changeSetting(RandomDataGenerator random, State state, RandWalkEnv env, Properties props) throws Exception {
    // pick a random property
    int choice = random.nextInt(0, settings.length - 1);
    Setting setting = settings[choice];
    // generate a random value
    long newValue = random.nextLong(setting.min, setting.max);
    state.set(LAST_SETTING, "" + choice);
    log.debug("Setting " + setting.property.getKey() + " to " + newValue);
    env.getAccumuloClient().instanceOperations().setProperty(setting.property.getKey(), "" + newValue);
  }

}
