// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

package com.android.tools.r8.kotlin;

import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexDefinitionSupplier;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.kotlin.Kotlin.ClassClassifiers;
import com.android.tools.r8.shaking.EnqueuerMetadataTraceable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import kotlinx.metadata.KmAnnotationArgument;
import kotlinx.metadata.KmAnnotationArgument.AnnotationValue;
import kotlinx.metadata.KmAnnotationArgument.ArrayValue;
import kotlinx.metadata.KmAnnotationArgument.EnumValue;
import kotlinx.metadata.KmAnnotationArgument.KClassValue;

abstract class KotlinAnnotationArgumentInfo implements EnqueuerMetadataTraceable {

  private static final Map<String, KotlinAnnotationArgumentInfo> EMPTY_ARGUMENTS =
      ImmutableMap.of();

  abstract boolean rewrite(Consumer<KmAnnotationArgument> consumer, AppView<?> appView);

  private static KotlinAnnotationArgumentInfo createArgument(
      KmAnnotationArgument arg, DexItemFactory factory) {
    if (arg instanceof KClassValue) {
      return KotlinAnnotationClassValueInfo.create((KClassValue) arg, factory);
    } else if (arg instanceof EnumValue) {
      return KotlinAnnotationEnumValueInfo.create((EnumValue) arg, factory);
    } else if (arg instanceof AnnotationValue) {
      return KotlinAnnotationAnnotationValueInfo.create((AnnotationValue) arg, factory);
    } else if (arg instanceof ArrayValue) {
      return KotlinAnnotationArrayValueInfo.create((ArrayValue) arg, factory);
    } else {
      return KotlinAnnotationPrimitiveArgumentInfo.create(arg);
    }
  }

  static Map<String, KotlinAnnotationArgumentInfo> create(
      Map<String, KmAnnotationArgument> arguments, DexItemFactory factory) {
    if (arguments.isEmpty()) {
      return EMPTY_ARGUMENTS;
    }
    LinkedHashMap<String, KotlinAnnotationArgumentInfo> modeled = new LinkedHashMap<>();
    arguments.forEach((key, arg) -> modeled.put(key, createArgument(arg, factory)));
    return modeled;
  }

  private static class KotlinAnnotationClassValueInfo extends KotlinAnnotationArgumentInfo {

    private final KotlinTypeReference value;
    private final int arrayDimensionCount;

    private KotlinAnnotationClassValueInfo(KotlinTypeReference value, int arrayDimensionCount) {
      this.value = value;
      this.arrayDimensionCount = arrayDimensionCount;
    }

    private static KotlinAnnotationClassValueInfo create(KClassValue arg, DexItemFactory factory) {
      return new KotlinAnnotationClassValueInfo(
          KotlinTypeReference.fromBinaryName(arg.getClassName(), factory, arg.getClassName()),
          arg.getArrayDimensionCount());
    }

    @Override
    public void trace(DexDefinitionSupplier definitionSupplier) {
      value.trace(definitionSupplier);
    }

    @Override
    boolean rewrite(Consumer<KmAnnotationArgument> consumer, AppView<?> appView) {
      return value.toRenamedBinaryNameOrDefault(
          rewrittenValue -> consumer.accept(new KClassValue(rewrittenValue, arrayDimensionCount)),
          appView,
          ClassClassifiers.anyName);
    }
  }

  private static class KotlinAnnotationEnumValueInfo extends KotlinAnnotationArgumentInfo {

    private final KotlinTypeReference enumClassName;
    private final String enumEntryName;

    private KotlinAnnotationEnumValueInfo(KotlinTypeReference enumClassName, String enumEntryName) {
      this.enumClassName = enumClassName;
      this.enumEntryName = enumEntryName;
    }

    private static KotlinAnnotationEnumValueInfo create(EnumValue arg, DexItemFactory factory) {
      return new KotlinAnnotationEnumValueInfo(
          KotlinTypeReference.fromBinaryName(
              arg.getEnumClassName(), factory, arg.getEnumClassName()),
          arg.getEnumEntryName());
    }

    @Override
    public void trace(DexDefinitionSupplier definitionSupplier) {
      enumClassName.trace(definitionSupplier);
    }

    @Override
    boolean rewrite(Consumer<KmAnnotationArgument> consumer, AppView<?> appView) {
      return enumClassName.toRenamedBinaryNameOrDefault(
          rewrittenEnumClassName ->
              consumer.accept(new EnumValue(rewrittenEnumClassName, enumEntryName)),
          appView,
          ClassClassifiers.anyName);
    }
  }

  private static class KotlinAnnotationAnnotationValueInfo extends KotlinAnnotationArgumentInfo {

    private final KotlinAnnotationInfo value;

    private KotlinAnnotationAnnotationValueInfo(KotlinAnnotationInfo value) {
      this.value = value;
    }

    private static KotlinAnnotationAnnotationValueInfo create(
        AnnotationValue arg, DexItemFactory factory) {
      return new KotlinAnnotationAnnotationValueInfo(
          KotlinAnnotationInfo.create(arg.getAnnotation(), factory));
    }

    @Override
    public void trace(DexDefinitionSupplier definitionSupplier) {
      value.trace(definitionSupplier);
    }

    @Override
    boolean rewrite(Consumer<KmAnnotationArgument> consumer, AppView<?> appView) {
      return value.rewrite(
          rewrittenAnnotation -> {
            if (rewrittenAnnotation != null) {
              consumer.accept(new AnnotationValue(rewrittenAnnotation));
            }
          },
          appView);
    }
  }

  private static class KotlinAnnotationArrayValueInfo extends KotlinAnnotationArgumentInfo {

    private static final KotlinAnnotationArrayValueInfo EMPTY =
        new KotlinAnnotationArrayValueInfo(ImmutableList.of());

    private final List<KotlinAnnotationArgumentInfo> value;

    private KotlinAnnotationArrayValueInfo(List<KotlinAnnotationArgumentInfo> value) {
      this.value = value;
    }

    private static KotlinAnnotationArrayValueInfo create(ArrayValue arg, DexItemFactory factory) {
      if (arg.getElements().isEmpty()) {
        return EMPTY;
      }
      ImmutableList.Builder<KotlinAnnotationArgumentInfo> builder = ImmutableList.builder();
      for (KmAnnotationArgument argument : arg.getElements()) {
        builder.add(createArgument(argument, factory));
      }
      return new KotlinAnnotationArrayValueInfo(builder.build());
    }

    @Override
    public void trace(DexDefinitionSupplier definitionSupplier) {
      for (KotlinAnnotationArgumentInfo kotlinAnnotationArgumentInfo : value) {
        kotlinAnnotationArgumentInfo.trace(definitionSupplier);
      }
    }

    @Override
    boolean rewrite(Consumer<KmAnnotationArgument> consumer, AppView<?> appView) {
      List<KmAnnotationArgument> rewrittenArguments = new ArrayList<>();
      boolean rewritten = false;
      for (KotlinAnnotationArgumentInfo kotlinAnnotationArgumentInfo : value) {
        rewritten |=
            kotlinAnnotationArgumentInfo.rewrite(
                rewrittenArg -> {
                  if (rewrittenArg != null) {
                    rewrittenArguments.add(rewrittenArg);
                  }
                },
                appView);
      }
      consumer.accept(new ArrayValue(rewrittenArguments));
      return rewritten;
    }
  }

  private static class KotlinAnnotationPrimitiveArgumentInfo extends KotlinAnnotationArgumentInfo {

    private final KmAnnotationArgument argument;

    private KotlinAnnotationPrimitiveArgumentInfo(KmAnnotationArgument argument) {
      this.argument = argument;
    }

    private static KotlinAnnotationPrimitiveArgumentInfo create(KmAnnotationArgument argument) {
      return new KotlinAnnotationPrimitiveArgumentInfo(argument);
    }

    @Override
    public void trace(DexDefinitionSupplier definitionSupplier) {
      // Nothing to trace
    }

    @Override
    boolean rewrite(Consumer<KmAnnotationArgument> consumer, AppView<?> appView) {
      consumer.accept(argument);
      return false;
    }
  }
}
