// 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 com.google.common.collect.ImmutableList;
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));
    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;
  }

  /**
   * Returns a class name generated from the given {@code element}.
   *
   * <p>For {@code Foo.Bar} this is {@code Foo_Bar_suffix}.
   */
  static String getGeneratedName(Element element, String suffix) {
    ImmutableList.Builder<String> classNamesBuilder = new ImmutableList.Builder<>();
    classNamesBuilder.add(suffix);
    do {
      classNamesBuilder.add(element.getSimpleName().toString());
      element = element.getEnclosingElement();
    } while (element instanceof TypeElement);
    return classNamesBuilder.build().reverse().stream().collect(Collectors.joining("_"));
  }

  /**
   * 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();
  }

  static boolean isSubType(TypeMirror type, Class<?> clazz, ProcessingEnvironment env) {
    return env.getTypeUtils().isSubtype(type, getType(clazz, env));
  }
}
