// Copyright 2017 The Bazel Authors. All rights reserved.
//
// 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 com.google.devtools.build.lib.skyframe.serialization;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ClassToInstanceMap;
import com.google.common.collect.ImmutableClassToInstanceMap;
import com.google.common.collect.Maps;
import com.google.protobuf.ByteString;
import com.google.protobuf.CodedInputStream;
import com.google.protobuf.CodedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import javax.annotation.Nullable;

/**
 * Wrapper for the minutiae of serializing and deserializing objects using {@link ObjectCodec}s,
 * serving as a layer between the streaming-oriented {@link ObjectCodec} interface and users.
 */
public class ObjectCodecs {
  /**
   * Default initial capacity of the output byte stream.
   *
   * <p>The same value that ByteArrayOutputStream's default constructor uses.
   */
  private static final int DEFAULT_OUTPUT_CAPACITY = 32;

  private final ImmutableSerializationContext serializationContext;
  private final ImmutableDeserializationContext deserializationContext;

  /**
   * Creates an instance using the supplied {@code ObjectCodecRegistry} for looking up {@link
   * ObjectCodec}s.
   */
  public ObjectCodecs(
      ObjectCodecRegistry codecRegistry, ImmutableClassToInstanceMap<Object> dependencies) {
    serializationContext = new ImmutableSerializationContext(codecRegistry, dependencies);
    deserializationContext = new ImmutableDeserializationContext(codecRegistry, dependencies);
  }

  public ObjectCodecs(ObjectCodecRegistry codecRegistry) {
    this(codecRegistry, ImmutableClassToInstanceMap.of());
  }

  public ObjectCodecs(ImmutableClassToInstanceMap<Object> dependencies) {
    this(AutoRegistry.get(), dependencies);
  }

  public ObjectCodecs() {
    this(AutoRegistry.get(), ImmutableClassToInstanceMap.of());
  }

  @Nullable
  public byte[] getCodecRegistryChecksum() {
    return getCodecRegistry().getChecksum();
  }

  @VisibleForTesting // private
  public ImmutableSerializationContext getSerializationContextForTesting() {
    return serializationContext;
  }

  @VisibleForTesting // private
  public MemoizingSerializationContext getMemoizingSerializationContextForTesting() {
    return MemoizingSerializationContext.createForTesting(getCodecRegistry(), getDependencies());
  }

  @VisibleForTesting // private
  public SharedValueSerializationContext getSharedValueSerializationContextForTesting(
      FingerprintValueService fingerprintValueService) {
    return SharedValueSerializationContext.createForTesting(
        getCodecRegistry(), getDependencies(), fingerprintValueService);
  }

  @VisibleForTesting // private
  public ObjectCodecs withDependencyOverridesForTesting(ClassToInstanceMap<?> dependencyOverrides) {
    return new ObjectCodecs(
        getCodecRegistry(), overrideDependencies(getDependencies(), dependencyOverrides));
  }

  @VisibleForTesting // private
  public ImmutableDeserializationContext getDeserializationContextForTesting() {
    return deserializationContext;
  }

  @VisibleForTesting // private
  public MemoizingDeserializationContext getMemoizingDeserializationContextForTesting() {
    return MemoizingDeserializationContext.createForTesting(getCodecRegistry(), getDependencies());
  }

  @VisibleForTesting // private
  public SharedValueDeserializationContext getSharedValueDeserializationContextForTesting(
      FingerprintValueService fingerprintValueService) {
    return SharedValueDeserializationContext.createForTesting(
        getCodecRegistry(), getDependencies(), fingerprintValueService);
  }

  /**
   * Serializes {@code obj} using a naive traversal.
   *
   * <p>This approach works well for simple, tree values. However, the naive traversal will stack
   * overflow on cyclic structures and can exhibit exponential complexity for DAGs.
   */
  public ByteString serialize(Object subject) throws SerializationException {
    ByteString.Output bytesOut = ByteString.newOutput();
    CodedOutputStream codedOut = CodedOutputStream.newInstance(bytesOut);
    try {
      serializationContext.serialize(subject, codedOut);
      codedOut.flush();
    } catch (IOException e) {
      throw new SerializationException("Failed to serialize " + subject, e);
    }
    return bytesOut.toByteString();
  }

  public void serialize(Object subject, CodedOutputStream codedOut) throws SerializationException {
    try {
      serializationContext.serialize(subject, codedOut);
    } catch (IOException e) {
      throw new SerializationException("Failed to serialize " + subject, e);
    }
  }

  /** Serializes {@code subject} using memoization. */
  public ByteString serializeMemoized(@Nullable Object subject) throws SerializationException {
    return MemoizingSerializationContext.serializeToByteString(
        getCodecRegistry(),
        getDependencies(),
        subject,
        DEFAULT_OUTPUT_CAPACITY,
        CodedOutputStream.DEFAULT_BUFFER_SIZE);
  }

  /**
   * Serializes {@code subject} using memoization, with {@code byte[]} output.
   *
   * @param outputCapacity the initial capacity of the {@link ByteArrayOutputStream}
   * @param bufferSize size passed to {@link CodedOutputStream#newInstance}
   */
  public byte[] serializeMemoizedToBytes(
      @Nullable Object subject, int outputCapacity, int bufferSize) throws SerializationException {
    return MemoizingSerializationContext.serializeToBytes(
        getCodecRegistry(), getDependencies(), subject, outputCapacity, bufferSize);
  }

  /** Serializes {@code subject} using a {@link SharedValueSerializationContext}. */
  public SerializationResult<ByteString> serializeMemoizedAndBlocking(
      FingerprintValueService fingerprintValueService, Object subject)
      throws SerializationException {
    return SharedValueSerializationContext.serializeToResult(
        getCodecRegistry(), getDependencies(), fingerprintValueService, subject);
  }

  /**
   * Serializes {@code subject} using a {@link SharedValueSerializationContext}.
   *
   * @param dependencyOverrides dependencies to override, see {@link #overrideDependencies}
   */
  public SerializationResult<ByteString> serializeMemoizedAndBlocking(
      FingerprintValueService fingerprintValueService,
      Object subject,
      ImmutableClassToInstanceMap<?> dependencyOverrides)
      throws SerializationException {
    return SharedValueSerializationContext.serializeToResult(
        getCodecRegistry(),
        overrideDependencies(getDependencies(), dependencyOverrides),
        fingerprintValueService,
        subject);
  }

  public Object deserialize(byte[] data) throws SerializationException {
    return deserialize(CodedInputStream.newInstance(data));
  }

  public Object deserialize(ByteString data) throws SerializationException {
    return deserialize(data.newCodedInput());
  }

  public Object deserialize(CodedInputStream codedIn) throws SerializationException {
    return deserializeStreamFully(codedIn, deserializationContext);
  }

  public Object deserializeMemoized(ByteString data) throws SerializationException {
    return MemoizingDeserializationContext.deserializeMemoized(
        getCodecRegistry(), getDependencies(), data);
  }

  public Object deserializeMemoized(byte[] data) throws SerializationException {
    return MemoizingDeserializationContext.deserializeMemoized(
        getCodecRegistry(), getDependencies(), data);
  }

  public Object deserializeMemoizedAndBlocking(
      FingerprintValueService fingerprintValueService, ByteString data)
      throws SerializationException {
    return SharedValueDeserializationContext.deserializeWithSharedValues(
        getCodecRegistry(), getDependencies(), fingerprintValueService, data);
  }

  public Object deserializeMemoizedAndBlocking(
      FingerprintValueService fingerprintValueService,
      ByteString data,
      ImmutableClassToInstanceMap<?> dependencyOverrides)
      throws SerializationException {
    return SharedValueDeserializationContext.deserializeWithSharedValues(
        getCodecRegistry(),
        overrideDependencies(getDependencies(), dependencyOverrides),
        fingerprintValueService,
        data);
  }

  static Object deserializeStreamFully(CodedInputStream codedIn, DeserializationContext context)
      throws SerializationException {
    // Allows access to buffer without copying (although this means buffer may be pinned in memory).
    codedIn.enableAliasing(true);
    Object result;
    try {
      result = context.deserialize(codedIn);
    } catch (IOException e) {
      throw new SerializationException("Failed to deserialize data", e);
    }
    try {
      if (!codedIn.isAtEnd()) {
        throw new SerializationException(
            "input stream not exhausted after deserializing " + result);
      }
    } catch (IOException e) {
      throw new SerializationException("Error checking for end of stream with " + result, e);
    }
    return result;
  }

  // It's awkward that values are read from `serializationContext` instead of
  // `deserializationContext` and that they always have the same values. There's not much cohesion
  // between these two, however, so introducing an extra layer of indirection to store a (codec
  // registry, dependencies) tuple doesn't appear to be worth it.

  private ObjectCodecRegistry getCodecRegistry() {
    return serializationContext.getCodecRegistry();
  }

  private ImmutableClassToInstanceMap<Object> getDependencies() {
    return serializationContext.getDependencies();
  }

  /**
   * Returns a new dependency map composed by applying overrides to {@code dependencies}.
   *
   * <p>The given {@code dependencyOverrides} may contain keys already present (in which case the
   * dependency will be replaced) or new keys (in which case the dependency will be added).
   */
  private static ImmutableClassToInstanceMap<Object> overrideDependencies(
      ImmutableClassToInstanceMap<Object> dependencies, ClassToInstanceMap<?> dependencyOverrides) {
    return ImmutableClassToInstanceMap.builder()
        .putAll(Maps.filterKeys(dependencies, k -> !dependencyOverrides.containsKey(k)))
        .putAll(dependencyOverrides)
        .build();
  }
}
