// Copyright 2018 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 static com.google.common.base.Preconditions.checkNotNull;
import static com.google.devtools.build.lib.unsafe.UnsafeProvider.unsafe;

import com.google.common.collect.ImmutableClassToInstanceMap;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.errorprone.annotations.ForOverride;
import com.google.protobuf.CodedInputStream;
import java.io.IOException;
import javax.annotation.Nullable;

/**
 * Stateful class for providing additional context to a single deserialization "session". This class
 * is thread-safe so long as {@link #deserializer} is null. If it is not null, this class is not
 * thread-safe and should only be accessed on a single thread for deserializing one serialized
 * object (that may contain other serialized objects inside it).
 */
public abstract class DeserializationContext implements AsyncDeserializationContext {
  private final ObjectCodecRegistry registry;
  private final ImmutableClassToInstanceMap<Object> dependencies;

  DeserializationContext(
      ObjectCodecRegistry registry, ImmutableClassToInstanceMap<Object> dependencies) {
    this.registry = registry;
    this.dependencies = dependencies;
  }

  @Nullable
  @SuppressWarnings({"TypeParameterUnusedInFormals", "unchecked"})
  public final <T> T deserialize(CodedInputStream codedIn)
      throws IOException, SerializationException {
    return (T) makeSynchronous(processTagAndDeserialize(codedIn));
  }

  /**
   * Deserializes into {@code parent} using {@code setter}.
   *
   * <p>This allows custom processing of the deserialized object.
   */
  @Override
  public <T> void deserialize(CodedInputStream codedIn, T parent, FieldSetter<? super T> setter)
      throws IOException, SerializationException {
    Object value = deserialize(codedIn);
    if (value == null) {
      return;
    }
    setter.set(parent, value);
  }

  @Override
  public void deserialize(CodedInputStream codedIn, Object parent, long offset)
      throws IOException, SerializationException {
    unsafe().putObject(parent, offset, deserialize(codedIn));
  }

  @Override
  public void deserialize(CodedInputStream codedIn, Object parent, long offset, Runnable done)
      throws IOException, SerializationException {
    deserialize(codedIn, parent, offset);
    done.run();
  }

  @Override
  public <T> void getSharedValue(
      CodedInputStream codedIn,
      @Nullable Object distinguisher,
      DeferredObjectCodec<?> codec,
      T parent,
      FieldSetter<? super T> setter)
      throws IOException, SerializationException {
    throw new UnsupportedOperationException();
  }

  @Override
  public final <T> T getDependency(Class<T> type) {
    return checkNotNull(dependencies.getInstance(type), "Missing dependency of type %s", type);
  }

  /** Returns a copy of the context with reset state. */
  // TODO: b/297857068 - Only the NestedSetCodecWithStore and HeaderInfoCodec call this method.
  // Delete it when it is no longer needed.
  public abstract DeserializationContext getFreshContext();

  final ObjectCodecRegistry getRegistry() {
    return registry;
  }

  final ImmutableClassToInstanceMap<Object> getDependencies() {
    return dependencies;
  }

  /**
   * Deserializes from {@code codedIn} using {@code codec}.
   *
   * <p>This extension point allows the implementation optionally apply memoization logic.
   *
   * <p>Returns either a deserialized value or a {@link ListenableFuture}. A {@link
   * ListenableFuture} is only possible for {@link SharedValueDeserializationContext}.
   */
  @ForOverride
  abstract Object deserializeAndMaybeMemoize(ObjectCodec<?> codec, CodedInputStream codedIn)
      throws SerializationException, IOException;

  /**
   * Reads the tag and uses its value to deserialize the next value.
   *
   * <ul>
   *   <li>null, if the value was null;
   *   <li>a {@link ListenableFuture} that produces the value; or
   *   <li>the value directly.
   * </ul>
   *
   * <p>{@link ListenableFuture} is only possible for {@link SharedValueDeserializationContext}.
   */
  @Nullable
  final Object processTagAndDeserialize(CodedInputStream codedIn)
      throws SerializationException, IOException {
    int tag = codedIn.readSInt32();
    if (tag == 0) {
      return null;
    }
    if (tag < 0) {
      // Subtracts 1 to undo transformation from SerializationContext to avoid null.
      return getMemoizedBackReference(-tag - 1);
    }
    Object constant = registry.maybeGetConstantByTag(tag);
    if (constant != null) {
      return constant;
    }
    // Performs deserialization using the specified codec.
    return deserializeAndMaybeMemoize(registry.getCodecDescriptorByTag(tag).getCodec(), codedIn);
  }

  @Nullable
  final Object maybeGetConstantByTag(int tag) {
    return registry.maybeGetConstantByTag(tag);
  }

  abstract Object getMemoizedBackReference(int memoIndex);

  /**
   * Returns the result value.
   *
   * <p>In the {@link SharedValueDeserializationContext}, the {@link deserializeAndMaybeMemoize} may
   * produce futures. This method is overridden to unwrap them.
   */
  @SuppressWarnings("CanIgnoreReturnValueSuggester")
  @ForOverride
  Object makeSynchronous(Object obj) throws SerializationException {
    return obj;
  }
}
