/*
 * Copyright 2017, Google Inc.
 * Licensed 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 io.opencensus.tags;

import static io.opencensus.tags.TagKey.TagType.TAG_BOOLEAN;
import static io.opencensus.tags.TagKey.TagType.TAG_LONG;
import static io.opencensus.tags.TagKey.TagType.TAG_STRING;

import com.google.auto.value.AutoValue;
import com.google.common.base.Preconditions;
import com.google.instrumentation.internal.StringUtil;
import javax.annotation.concurrent.Immutable;

/**
 * A key to a value stored in a {@link TagMap}.
 *
 * @param <TagValueT> The type of value that can be paired with this {@code TagKey}. {@code TagKey}s
 *     can only be instantiated with types {@code String}, {@code Long}, and {@code Boolean}.
 */
@Immutable
@AutoValue
public abstract class TagKey<TagValueT> {
  /** The maximum length for a tag key name. */
  public static final int MAX_LENGTH = StringUtil.MAX_LENGTH;

  enum TagType {
    TAG_STRING,
    TAG_LONG,
    TAG_BOOLEAN
  }

  TagKey() {}

  /**
   * Constructs a {@code TagKey<String>} from the given string. The string must meet the following
   * requirements:
   *
   * <ol>
   *   <li>It cannot be longer than {@link #MAX_LENGTH}.
   *   <li>It can only contain printable ASCII characters.
   * </ol>
   *
   * @param name the name of the key.
   * @throws IllegalArgumentException if the name is not valid.
   */
  public static TagKey<String> createString(String name) {
    Preconditions.checkArgument(StringUtil.isValid(name));
    return createStringInternal(name);
  }

  private static TagKey<String> createStringInternal(String name) {
    return new AutoValue_TagKey<String>(name, TAG_STRING);
  }

  /**
   * Constructs a {@code TagKey<Long>} from the given string. The string must meet the following
   * requirements:
   *
   * <ol>
   *   <li>It cannot be longer than {@link #MAX_LENGTH}.
   *   <li>It can only contain printable ASCII characters.
   * </ol>
   *
   * @param name the name of the key.
   * @throws IllegalArgumentException if the name is not valid.
   */
  // TODO(sebright): Make this public once we support types other than String.
  static TagKey<Long> createLong(String name) {
    Preconditions.checkArgument(StringUtil.isValid(name));
    return createLongInternal(name);
  }

  private static TagKey<Long> createLongInternal(String name) {
    return new AutoValue_TagKey<Long>(name, TAG_LONG);
  }

  /**
   * Constructs a {@code TagKey<Boolean>} from the given string. The string must meet the following
   * requirements:
   *
   * <ol>
   *   <li>It cannot be longer than {@link #MAX_LENGTH}.
   *   <li>It can only contain printable ASCII characters.
   * </ol>
   *
   * @param name the name of the key.
   * @throws IllegalArgumentException if the name is not valid.
   */
  // TODO(sebright): Make this public once we support types other than String.
  static TagKey<Boolean> createBoolean(String name) {
    Preconditions.checkArgument(StringUtil.isValid(name));
    return createBooleanInternal(name);
  }

  private static TagKey<Boolean> createBooleanInternal(String name) {
    return new AutoValue_TagKey<Boolean>(name, TAG_BOOLEAN);
  }

  abstract String getName();

  abstract TagType getTagType();
}

@@ -1532,28 +1532,28 @@
 ey%3CString%3E%7D 
-from
+with
  the given s
@@ -1547,32 +1547,43 @@
 h the given 
-string. 
+name.%0A   *%0A   * %3Cp%3E
 The string m
@@ -1596,37 +1596,32 @@
 et the following
-%0A   *
  requirements:%0A 
@@ -2213,20 +2213,20 @@
 %3CLong%3E%7D 
-from
+with
  the giv
@@ -2224,32 +2224,43 @@
 h the given 
-string. 
+name.%0A   *%0A   * %3Cp%3E
 The string m
@@ -2273,37 +2273,32 @@
 et the following
-%0A   *
  requirements:%0A 
@@ -2955,12 +2955,12 @@
 n%3E%7D 
-from
+with
  the
@@ -2970,16 +2970,27 @@
 ven 
-string. 
+name.%0A   *%0A   * %3Cp%3E
 The 
@@ -3019,21 +3019,16 @@
 ollowing
-%0A   *
  require

Reword TagKey Javadocs.