/*
 * 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.core.client.admin;

import static com.google.common.base.Preconditions.checkArgument;
import static java.util.Objects.requireNonNull;

import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;
import java.util.SortedSet;

import org.apache.accumulo.core.client.AccumuloException;
import org.apache.accumulo.core.client.IteratorSetting;
import org.apache.accumulo.core.client.impl.TableOperationsHelper;
import org.apache.accumulo.core.client.sample.SamplerConfiguration;
import org.apache.accumulo.core.client.summary.Summarizer;
import org.apache.accumulo.core.client.summary.SummarizerConfiguration;
import org.apache.accumulo.core.conf.Property;
import org.apache.accumulo.core.iterators.IteratorUtil;
import org.apache.accumulo.core.iterators.IteratorUtil.IteratorScope;
import org.apache.accumulo.core.iterators.user.VersioningIterator;
import org.apache.accumulo.core.sample.impl.SamplerConfigurationImpl;
import org.apache.accumulo.core.summary.SummarizerConfigurationUtil;
import org.apache.accumulo.core.util.LocalityGroupUtil;
import org.apache.hadoop.io.Text;

import com.google.common.collect.ImmutableSortedSet;

/**
 * This object stores table creation parameters. Currently includes: {@link TimeType}, whether to
 * include default iterators, and user-specified initial properties
 *
 * @since 1.7.0
 */
public class NewTableConfiguration {

  private static final TimeType DEFAULT_TIME_TYPE = TimeType.MILLIS;
  private TimeType timeType = DEFAULT_TIME_TYPE;

  private static final InitialTableState DEFAULT_CREATION_MODE = InitialTableState.ONLINE;
  private InitialTableState initialTableState = DEFAULT_CREATION_MODE;

  private boolean limitVersion = true;

  private Map<String,String> properties = Collections.emptyMap();
  private Map<String,String> samplerProps = Collections.emptyMap();
  private Map<String,String> summarizerProps = Collections.emptyMap();
  private Map<String,String> localityProps = Collections.emptyMap();
  private final Map<String,String> iteratorProps = new HashMap<>();
  private SortedSet<Text> splitProps = Collections.emptySortedSet();

  private void checkDisjoint(Map<String,String> props, Map<String,String> derivedProps,
      String kind) {
    checkArgument(Collections.disjoint(props.keySet(), derivedProps.keySet()),
        "Properties and derived %s properties are not disjoint", kind);
  }

  /**
   * Configure logical or millisecond time for tables created with this configuration.
   *
   * @param tt
   *          the time type to use; defaults to milliseconds
   * @return this
   */
  public NewTableConfiguration setTimeType(TimeType tt) {
    checkArgument(tt != null, "TimeType is null");
    this.timeType = tt;
    return this;
  }

  /**
   * Retrieve the time type currently configured.
   *
   * @return the time type
   */
  public TimeType getTimeType() {
    return timeType;
  }

  /**
   * Currently the only default iterator is the {@link VersioningIterator}. This method will cause
   * the table to be created without that iterator, or any others which may become defaults in the
   * future.
   *
   * @return this
   */
  public NewTableConfiguration withoutDefaultIterators() {
    this.limitVersion = false;
    return this;
  }

  /**
   * Create the new table in an offline state.
   *
   * @return this
   *
   * @since 2.0.0
   */
  public NewTableConfiguration createOffline() {
    this.initialTableState = InitialTableState.OFFLINE;
    return this;
  }

  /**
   * Return value indicating whether table is to be created in offline or online mode.
   *
   * @return 1 if true; 0 otherwise.
   *
   * @since 2.0.0
   */
  public InitialTableState getInitialTableState() {
    return initialTableState;
  }

  /**
   * Sets additional properties to be applied to tables created with this configuration. Additional
   * calls to this method replace properties set by previous calls.
   *
   * @param props
   *          additional properties to add to the table when it is created
   * @return this
   */
  public NewTableConfiguration setProperties(Map<String,String> props) {
    checkArgument(props != null, "properties is null");
    checkDisjoint(props, samplerProps, "sampler");
    checkDisjoint(props, summarizerProps, "summarizer");
    checkDisjoint(props, localityProps, "locality group");
    checkDisjoint(props, iteratorProps, "iterator");
    checkTableProperties(props);
    this.properties = new HashMap<>(props);
    return this;
  }

  /**
   * Retrieves the complete set of currently configured table properties to be applied to a table
   * when this configuration object is used.
   *
   * @return the current properties configured
   */
  public Map<String,String> getProperties() {
    Map<String,String> propertyMap = new HashMap<>();

    if (limitVersion)
      propertyMap.putAll(IteratorUtil.generateInitialTableProperties(limitVersion));

    propertyMap.putAll(summarizerProps);
    propertyMap.putAll(samplerProps);
    propertyMap.putAll(properties);
    propertyMap.putAll(iteratorProps);
    propertyMap.putAll(localityProps);
    return Collections.unmodifiableMap(propertyMap);
  }

  /**
   * Return Collection of split values.
   *
   * @return Collection containing splits associated with this NewTableConfiguration object.
   *
   * @since 2.0.0
   */
  public Collection<Text> getSplits() {
    return splitProps;
  }

  /**
   * Enable building a sample data set on the new table using the given sampler configuration.
   *
   * @since 1.8.0
   */
  public NewTableConfiguration enableSampling(SamplerConfiguration samplerConfiguration) {
    requireNonNull(samplerConfiguration);
    Map<String,String> tmp = new SamplerConfigurationImpl(samplerConfiguration)
        .toTablePropertiesMap();
    checkDisjoint(properties, tmp, "sampler");
    this.samplerProps = tmp;
    return this;
  }

  /**
   * Enables creating summary statistics using {@link Summarizer}'s for the new table.
   *
   * @since 2.0.0
   */
  public NewTableConfiguration enableSummarization(SummarizerConfiguration... configs) {
    requireNonNull(configs);
    Map<String,String> tmp = SummarizerConfigurationUtil
        .toTablePropertiesMap(Arrays.asList(configs));
    checkDisjoint(properties, tmp, "summarizer");
    summarizerProps = tmp;
    return this;
  }

  /**
   * Configures a table's locality groups prior to initial table creation.
   *
   * Allows locality groups to be set prior to table creation. Additional calls to this method prior
   * to table creation will overwrite previous locality group mappings.
   *
   * @param groups
   *          mapping of locality group names to column families in the locality group
   *
   * @since 2.0.0
   *
   * @see TableOperations#setLocalityGroups
   */
  public NewTableConfiguration setLocalityGroups(Map<String,Set<Text>> groups) {
    // ensure locality groups do not overlap
    LocalityGroupUtil.ensureNonOverlappingGroups(groups);
    Map<String,String> tmp = new HashMap<>();
    for (Entry<String,Set<Text>> entry : groups.entrySet()) {
      Set<Text> colFams = entry.getValue();
      String value = LocalityGroupUtil.encodeColumnFamilies(colFams);
      tmp.put(Property.TABLE_LOCALITY_GROUP_PREFIX + entry.getKey(), value);
    }
    tmp.put(Property.TABLE_LOCALITY_GROUPS.getKey(), String.join(",", groups.keySet()));
    checkDisjoint(properties, tmp, "locality groups");
    localityProps = tmp;
    return this;
  }

  /**
   * Create a new table with pre-configured splits from the provided input collection.
   *
   * @param splits
   *          A SortedSet of String values to be used as split points in a newly created table.
   * @return this
   *
   * @since 2.0.0
   */
  public NewTableConfiguration withSplits(final SortedSet<Text> splits) {
    checkArgument(splits != null, "splits set is null");
    checkArgument(!splits.isEmpty(), "splits set is empty");
    this.splitProps = ImmutableSortedSet.copyOf(splits);
    return this;
  }

  /**
   * Configure iterator settings for a table prior to its creation.
   *
   * Additional calls to this method before table creation will overwrite previous iterator
   * settings.
   *
   * @param setting
   *          object specifying the properties of the iterator
   *
   * @since 2.0.0
   *
   * @see TableOperations#attachIterator(String, IteratorSetting)
   */
  public NewTableConfiguration attachIterator(IteratorSetting setting) {
    return attachIterator(setting, EnumSet.allOf(IteratorScope.class));
  }

  /**
   * Configure iterator settings for a table prior to its creation.
   *
   * @param setting
   *          object specifying the properties of the iterator
   * @param scopes
   *          enumerated set of iterator scopes
   *
   * @since 2.0.0
   *
   * @see TableOperations#attachIterator(String, IteratorSetting, EnumSet)
   */
  public NewTableConfiguration attachIterator(IteratorSetting setting,
      EnumSet<IteratorScope> scopes) {
    Objects.requireNonNull(setting, "setting cannot be null!");
    Objects.requireNonNull(scopes, "scopes cannot be null!");
    try {
      TableOperationsHelper.checkIteratorConflicts(iteratorProps, setting, scopes);
    } catch (AccumuloException e) {
      throw new IllegalArgumentException("The specified IteratorSetting"
          + " conflicts with an iterator already defined on this NewTableConfiguration", e);
    }
    for (IteratorScope scope : scopes) {
      String root = String.format("%s%s.%s", Property.TABLE_ITERATOR_PREFIX,
          scope.name().toLowerCase(), setting.getName());
      for (Entry<String,String> prop : setting.getOptions().entrySet()) {
        iteratorProps.put(root + ".opt." + prop.getKey(), prop.getValue());
      }
      iteratorProps.put(root, setting.getPriority() + "," + setting.getIteratorClass());
      // verify that the iteratorProps assigned and the properties do not share any keys.
      checkDisjoint(properties, iteratorProps, "iterator");
    }
    return this;
  }

  /**
   * Verify the provided properties are valid table properties.
   */
  private void checkTableProperties(Map<String,String> props) {
    props.keySet().forEach((key) -> {
      if (!key.startsWith(Property.TABLE_PREFIX.toString())) {
        throw new IllegalArgumentException("'" + key + "' is not a valid table property");
      }
    });
  }
}
