// 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.ImmutableMap;
import com.google.protobuf.ByteString;
import com.google.protobuf.CodedInputStream;
import com.google.protobuf.CodedOutputStream;
import java.io.IOException;

/**
 * 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 {
  private final SerializationContext serializationContext;
  private final DeserializationContext deserializationContext;

  /**
   * Creates an instance using the supplied {@link ObjectCodecRegistry} for looking up {@link
   * ObjectCodec}s.
   */
  public ObjectCodecs(
      ObjectCodecRegistry codecRegistry, ImmutableMap<Class<?>, Object> dependencies) {
    serializationContext = new SerializationContext(codecRegistry, dependencies);
    deserializationContext = new DeserializationContext(codecRegistry, dependencies);
  }

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

  @VisibleForTesting
  public SerializationContext getSerializationContext() {
    return serializationContext;
  }

  @VisibleForTesting
  public DeserializationContext getDeserializationContext() {
    return deserializationContext;
  }

  public ByteString serialize(Object subject) throws SerializationException {
    return serializeToByteString(subject, this::serialize);
  }

  public void serialize(Object subject, CodedOutputStream codedOut) throws SerializationException {
    serializeImpl(subject, codedOut, serializationContext);
  }

  public ByteString serializeMemoized(Object subject) throws SerializationException {
    return serializeToByteString(subject, this::serializeMemoized);
  }

  public void serializeMemoized(Object subject, CodedOutputStream codedOut)
      throws SerializationException {
    serializeImpl(subject, codedOut, serializationContext.getMemoizingContext());
  }

  public SerializationResult<ByteString> serializeMemoizedAndBlocking(Object subject)
      throws SerializationException {
    SerializationContext memoizingContext =
        serializationContext.getMemoizingAndBlockingOnWriteContext();
    ByteString byteString =
        serializeToByteString(
            subject, (subj, codedOut) -> serializeImpl(subj, codedOut, memoizingContext));
    return SerializationResult.create(byteString, memoizingContext.createFutureToBlockWritingOn());
  }

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

  public Object deserialize(CodedInputStream codedIn) throws SerializationException {
    return deserializeImpl(codedIn, /*memoize=*/ false);
  }

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

  public Object deserializeMemoized(CodedInputStream codedIn) throws SerializationException {
    return deserializeImpl(codedIn, /*memoize=*/ true);
  }

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

  private Object deserializeImpl(CodedInputStream codedIn, boolean memoize)
      throws SerializationException {
    // Allows access to buffer without copying (although this means buffer may be pinned in memory).
    codedIn.enableAliasing(true);
    Object result;
    try {
      result =
          memoize
              ? deserializationContext.getMemoizingContext().deserialize(codedIn)
              : deserializationContext.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;
  }

  @FunctionalInterface
  private static interface SerializeCall {
    void serialize(Object subject, CodedOutputStream codedOut) throws SerializationException;
  }

  private static ByteString serializeToByteString(Object subject, SerializeCall wrapped)
      throws SerializationException {
    ByteString.Output resultOut = ByteString.newOutput();
    CodedOutputStream codedOut = CodedOutputStream.newInstance(resultOut);
    wrapped.serialize(subject, codedOut);
    try {
      codedOut.flush();
      return resultOut.toByteString();
    } catch (IOException e) {
      throw new SerializationException("Failed to serialize " + subject, e);
    }
  }
}
