// 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.autocodec;

import static com.google.devtools.build.lib.skyframe.serialization.autocodec.SerializationProcessorUtil.getGeneratedName;

import com.google.devtools.build.lib.skyframe.serialization.DeserializationContext;
import com.google.devtools.build.lib.skyframe.serialization.ObjectCodec;
import com.google.devtools.build.lib.skyframe.serialization.SerializationContext;
import com.google.devtools.build.lib.skyframe.serialization.SerializationException;
import com.google.protobuf.CodedInputStream;
import com.google.protobuf.CodedOutputStream;
import com.squareup.javapoet.AnnotationSpec;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.Element;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.MirroredTypesException;
import javax.lang.model.type.TypeMirror;

/** Static utilities for AutoCodec processors. */
class AutoCodecUtil {
  // Synthesized classes will have `_AutoCodec` suffix added.
  private static final String GENERATED_CLASS_NAME_SUFFIX = "AutoCodec";
  static final Class<AutoCodec> ANNOTATION = AutoCodec.class;

  /**
   * Initializes a builder for a class of the appropriate type.
   *
   * @param encodedType type being serialized
   */
  static TypeSpec.Builder initializeCodecClassBuilder(
      TypeElement encodedType, ProcessingEnvironment env) {
    TypeSpec.Builder builder = TypeSpec.classBuilder(getCodecName(encodedType));
    builder.addAnnotation(
        AnnotationSpec.builder(ClassName.get(SuppressWarnings.class))
            .addMember("value", "$S", "unchecked")
            .addMember("value", "$S", "rawtypes")
            .build());
    return builder.addSuperinterface(
        ParameterizedTypeName.get(
            ClassName.get(ObjectCodec.class),
            TypeName.get(env.getTypeUtils().erasure(encodedType.asType()))));
  }

  static MethodSpec.Builder initializeGetEncodedClassMethod(
      TypeElement encodedType, ProcessingEnvironment env) {
    return MethodSpec.methodBuilder("getEncodedClass")
        .addModifiers(Modifier.PUBLIC)
        .addAnnotation(Override.class)
        .returns(
            ParameterizedTypeName.get(
                ClassName.get(Class.class),
                TypeName.get(env.getTypeUtils().erasure(encodedType.asType()))));
  }

  /**
   * Initializes the deserialize method.
   *
   * @param encodedType type being serialized
   */
  static MethodSpec.Builder initializeSerializeMethodBuilder(
      TypeElement encodedType, AutoCodec annotation, ProcessingEnvironment env) {
    MethodSpec.Builder builder =
        MethodSpec.methodBuilder("serialize")
            .addModifiers(Modifier.PUBLIC)
            .returns(void.class)
            .addAnnotation(Override.class)
            .addAnnotation(
                AnnotationSpec.builder(ClassName.get(SuppressWarnings.class))
                    .addMember("value", "$S", "unchecked")
                    .build())
            .addException(SerializationException.class)
            .addException(IOException.class)
            .addParameter(SerializationContext.class, "context")
            .addParameter(TypeName.get(env.getTypeUtils().erasure(encodedType.asType())), "input")
            .addParameter(CodedOutputStream.class, "codedOut");
    if (annotation.checkClassExplicitlyAllowed()) {
      builder.addStatement("context.checkClassExplicitlyAllowed(getEncodedClass(), input)");
    }
    List<? extends TypeMirror> explicitlyAllowedClasses;
    try {
      explicitlyAllowedClasses =
          Arrays.stream(annotation.explicitlyAllowClass())
              .map((clazz) -> getType(clazz, env))
              .collect(Collectors.toList());
    } catch (MirroredTypesException e) {
      explicitlyAllowedClasses = e.getTypeMirrors();
    }
    for (TypeMirror explicitlyAllowedClass : explicitlyAllowedClasses) {
      builder.addStatement("context.addExplicitlyAllowedClass($T.class)", explicitlyAllowedClass);
    }
    return builder;
  }

  /**
   * Initializes the deserialize method.
   *
   * @param encodedType type being serialized
   */
  static MethodSpec.Builder initializeDeserializeMethodBuilder(
      TypeElement encodedType, ProcessingEnvironment env) {
    MethodSpec.Builder builder =
        MethodSpec.methodBuilder("deserialize")
            .addModifiers(Modifier.PUBLIC)
            .returns(TypeName.get(env.getTypeUtils().erasure(encodedType.asType())))
            .addAnnotation(Override.class)
            .addException(SerializationException.class)
            .addException(IOException.class)
            .addParameter(DeserializationContext.class, "context")
            .addParameter(CodedInputStream.class, "codedIn");
    return builder;
  }

  /**
   * Name of the generated codec class.
   *
   * <p>For {@code Foo.Bar} this is {@code Foo_Bar_AutoCodec}.
   */
  private static String getCodecName(Element element) {
    return getGeneratedName(element, GENERATED_CLASS_NAME_SUFFIX);
  }

  static TypeMirror getType(Class<?> clazz, ProcessingEnvironment env) {
    return env.getElementUtils().getTypeElement(clazz.getCanonicalName()).asType();
  }
}
