/*
 * Copyright 2016-17, OpenCensus Authors
 *
 * 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.implcore.tags.propagation;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Charsets;
import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams;
import io.opencensus.implcore.internal.VarInt;
import io.opencensus.implcore.tags.TagContextImpl;
import io.opencensus.tags.InternalUtils;
import io.opencensus.tags.Tag;
import io.opencensus.tags.TagContext;
import io.opencensus.tags.TagKey;
import io.opencensus.tags.TagValue;
import io.opencensus.tags.propagation.TagContextDeserializationException;
import io.opencensus.tags.propagation.TagContextSerializationException;
import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * Methods for serializing and deserializing {@link TagContext}s.
 *
 * <p>The format defined in this class is shared across all implementations of OpenCensus. It allows
 * tags to propagate across requests.
 *
 * <p>OpenCensus tag context encoding:
 *
 * <ul>
 *   <li>Tags are encoded in single byte sequence. The version 0 format is:
 *   <li>{@code <version_id><encoded_tags>}
 *   <li>{@code <version_id> == a single byte, value 0}
 *   <li>{@code <encoded_tags> == (<tag_field_id><tag_encoding>)*}
 *       <ul>
 *         <li>{@code <tag_field_id>} == a single byte, value 0
 *         <li>{@code <tag_encoding>}:
 *             <ul>
 *               <li>{@code <tag_key_len><tag_key><tag_val_len><tag_val>}
 *                   <ul>
 *                     <li>{@code <tag_key_len>} == varint encoded integer
 *                     <li>{@code <tag_key>} == tag_key_len bytes comprising tag key name
 *                     <li>{@code <tag_val_len>} == varint encoded integer
 *                     <li>{@code <tag_val>} == tag_val_len bytes comprising UTF-8 string
 *                   </ul>
 *             </ul>
 *       </ul>
 * </ul>
 */
final class SerializationUtils {
  private SerializationUtils() {}

  @VisibleForTesting static final int VERSION_ID = 0;
  @VisibleForTesting static final int TAG_FIELD_ID = 0;
  // This size limit only applies to the bytes representing tag keys and values.
  @VisibleForTesting static final int TAGCONTEXT_SERIALIZED_SIZE_LIMIT = 8192;

  // Serializes a TagContext to the on-the-wire format.
  // Encoded tags are of the form: <version_id><encoded_tags>
  static byte[] serializeBinary(TagContext tags) throws TagContextSerializationException {
    // Use a ByteArrayDataOutput to avoid needing to handle IOExceptions.
    final ByteArrayDataOutput byteArrayDataOutput = ByteStreams.newDataOutput();
    byteArrayDataOutput.write(VERSION_ID);
    int totalChars = 0; // Here chars are equivalent to bytes, since we're using ascii chars.
    for (Iterator<Tag> i = InternalUtils.getTags(tags); i.hasNext(); ) {
      Tag tag = i.next();
      totalChars += tag.getKey().getName().length();
      totalChars += tag.getValue().asString().length();
      encodeTag(tag, byteArrayDataOutput);
    }
    if (totalChars > TAGCONTEXT_SERIALIZED_SIZE_LIMIT) {
      throw new TagContextSerializationException(
          "Size of TagContext exceeds the maximum serialized size "
              + TAGCONTEXT_SERIALIZED_SIZE_LIMIT);
    }
    return byteArrayDataOutput.toByteArray();
  }

  // Deserializes input to TagContext based on the binary format standard.
  // The encoded tags are of the form: <version_id><encoded_tags>
  static TagContextImpl deserializeBinary(byte[] bytes) throws TagContextDeserializationException {
    try {
      if (bytes.length == 0) {
        // Does not allow empty byte array.
        throw new TagContextDeserializationException("Input byte[] can not be empty.");
      }

      ByteBuffer buffer = ByteBuffer.wrap(bytes).asReadOnlyBuffer();
      int versionId = buffer.get();
      if (versionId > VERSION_ID || versionId < 0) {
        throw new TagContextDeserializationException(
            "Wrong Version ID: " + versionId + ". Currently supports version up to: " + VERSION_ID);
      }
      return new TagContextImpl(parseTags(buffer));
    } catch (BufferUnderflowException exn) {
      throw new TagContextDeserializationException(exn.toString()); // byte array format error.
    }
  }

  private static Map<TagKey, TagValue> parseTags(ByteBuffer buffer)
      throws TagContextDeserializationException {
    Map<TagKey, TagValue> tags = new HashMap<TagKey, TagValue>();
    int limit = buffer.limit();
    int totalChars = 0; // Here chars are equivalent to bytes, since we're using ascii chars.
    while (buffer.position() < limit) {
      int type = buffer.get();
      if (type == TAG_FIELD_ID) {
        TagKey key = createTagKey(decodeString(buffer));
        TagValue val = createTagValue(key, decodeString(buffer));
        totalChars += key.getName().length();
        totalChars += val.asString().length();
        tags.put(key, val);
      } else {
        // Stop parsing at the first unknown field ID, since there is no way to know its length.
        // TODO(sebright): Consider storing the rest of the byte array in the TagContext.
        break;
      }
    }
    if (totalChars > TAGCONTEXT_SERIALIZED_SIZE_LIMIT) {
      throw new TagContextDeserializationException(
          "Size of TagContext exceeds the maximum serialized size "
              + TAGCONTEXT_SERIALIZED_SIZE_LIMIT);
    }
    return tags;
  }

  // TODO(sebright): Consider exposing a TagKey name validation method to avoid needing to catch an
  // IllegalArgumentException here.
  private static final TagKey createTagKey(String name) throws TagContextDeserializationException {
    try {
      return TagKey.create(name);
    } catch (IllegalArgumentException e) {
      throw new TagContextDeserializationException("Invalid tag key: " + name, e);
    }
  }

  // TODO(sebright): Consider exposing a TagValue validation method to avoid needing to catch
  // an IllegalArgumentException here.
  private static final TagValue createTagValue(TagKey key, String value)
      throws TagContextDeserializationException {
    try {
      return TagValue.create(value);
    } catch (IllegalArgumentException e) {
      throw new TagContextDeserializationException(
          "Invalid tag value for key " + key + ": " + value, e);
    }
  }

  private static final void encodeTag(Tag tag, ByteArrayDataOutput byteArrayDataOutput) {
    byteArrayDataOutput.write(TAG_FIELD_ID);
    encodeString(tag.getKey().getName(), byteArrayDataOutput);
    encodeString(tag.getValue().asString(), byteArrayDataOutput);
  }

  private static final void encodeString(String input, ByteArrayDataOutput byteArrayDataOutput) {
    putVarInt(input.length(), byteArrayDataOutput);
    byteArrayDataOutput.write(input.getBytes(Charsets.UTF_8));
  }

  private static final void putVarInt(int input, ByteArrayDataOutput byteArrayDataOutput) {
    byte[] output = new byte[VarInt.varIntSize(input)];
    VarInt.putVarInt(input, output, 0);
    byteArrayDataOutput.write(output);
  }

  private static final String decodeString(ByteBuffer buffer) {
    int length = VarInt.getVarInt(buffer);
    StringBuilder builder = new StringBuilder();
    for (int i = 0; i < length; i++) {
      builder.append((char) buffer.get());
    }
    return builder.toString();
  }
}
