// Copyright (c) 2022, 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.keepanno.ast;

import com.google.common.collect.ImmutableMap;
import java.util.Map;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

public abstract class KeepTypePattern {

  public static KeepTypePattern any() {
    return Any.getInstance();
  }

  public static KeepTypePattern fromPrimitive(KeepPrimitiveTypePattern type) {
    return type.isAny() ? PrimitiveType.ANY : PrimitiveType.PRIMITIVES.get(type.getDescriptor());
  }

  public static KeepTypePattern fromArray(KeepArrayTypePattern type) {
    return new ArrayType(type);
  }

  public static KeepTypePattern fromClass(KeepQualifiedClassNamePattern type) {
    return new ClassType(type);
  }

  public static KeepTypePattern fromDescriptor(String typeDescriptor) {
    char c = typeDescriptor.charAt(0);
    if (c == 'L') {
      int end = typeDescriptor.length() - 1;
      if (typeDescriptor.charAt(end) != ';') {
        throw new KeepEdgeException("Invalid type descriptor: " + typeDescriptor);
      }
      return fromClass(KeepQualifiedClassNamePattern.exactFromDescriptor(typeDescriptor));
    }
    if (c == '[') {
      int dim = 1;
      while (typeDescriptor.charAt(dim) == '[') {
        dim++;
      }
      KeepTypePattern baseType = fromDescriptor(typeDescriptor.substring(dim));
      return fromArray(new KeepArrayTypePattern(baseType, dim));
    }
    PrimitiveType primitiveType = PrimitiveType.PRIMITIVES.get(typeDescriptor);
    if (primitiveType != null) {
      return primitiveType;
    }
    throw new KeepEdgeException("Invalid type descriptor: " + typeDescriptor);
  }

  public abstract <T> T apply(
      Supplier<T> onAny,
      Function<KeepPrimitiveTypePattern, T> onPrimitive,
      Function<KeepArrayTypePattern, T> onArray,
      Function<KeepQualifiedClassNamePattern, T> onClass);

  public final void match(
      Runnable onAny,
      Consumer<KeepPrimitiveTypePattern> onPrimitive,
      Consumer<KeepArrayTypePattern> onArray,
      Consumer<KeepQualifiedClassNamePattern> onClass) {
    apply(
        AstUtils.toVoidSupplier(onAny),
        AstUtils.toVoidFunction(onPrimitive),
        AstUtils.toVoidFunction(onArray),
        AstUtils.toVoidFunction(onClass));
  }

  public boolean isAny() {
    return false;
  }

  private static class Any extends KeepTypePattern {

    private static final Any INSTANCE = new Any();

    public static Any getInstance() {
      return INSTANCE;
    }

    @Override
    public <T> T apply(
        Supplier<T> onAny,
        Function<KeepPrimitiveTypePattern, T> onPrimitive,
        Function<KeepArrayTypePattern, T> onArray,
        Function<KeepQualifiedClassNamePattern, T> onClass) {
      return onAny.get();
    }

    @Override
    public boolean isAny() {
      return true;
    }

    @Override
    public boolean equals(Object obj) {
      return this == obj;
    }

    @Override
    public int hashCode() {
      return System.identityHashCode(this);
    }

    @Override
    public String toString() {
      return "<any>";
    }
  }

  private static class PrimitiveType extends KeepTypePattern {

    private static final PrimitiveType ANY = new PrimitiveType(KeepPrimitiveTypePattern.getAny());
    private static final Map<String, PrimitiveType> PRIMITIVES = populate();

    private static Map<String, PrimitiveType> populate() {
      ImmutableMap.Builder<String, PrimitiveType> builder = ImmutableMap.builder();
      KeepPrimitiveTypePattern.forEachPrimitive(
          primitive -> {
            builder.put(primitive.getDescriptor(), new PrimitiveType(primitive));
          });
      return builder.build();
    }

    private final KeepPrimitiveTypePattern type;

    private PrimitiveType(KeepPrimitiveTypePattern type) {
      this.type = type;
    }

    @Override
    public boolean equals(Object obj) {
      return this == obj;
    }

    @Override
    public int hashCode() {
      return System.identityHashCode(this);
    }

    @Override
    public String toString() {
      return type.getDescriptor();
    }

    @Override
    public <T> T apply(
        Supplier<T> onAny,
        Function<KeepPrimitiveTypePattern, T> onPrimitive,
        Function<KeepArrayTypePattern, T> onArray,
        Function<KeepQualifiedClassNamePattern, T> onClass) {
      return onPrimitive.apply(type);
    }
  }

  private static class ClassType extends KeepTypePattern {
    private final KeepQualifiedClassNamePattern type;

    public ClassType(KeepQualifiedClassNamePattern type) {
      this.type = type;
    }

    @Override
    public <T> T apply(
        Supplier<T> onAny,
        Function<KeepPrimitiveTypePattern, T> onPrimitive,
        Function<KeepArrayTypePattern, T> onArray,
        Function<KeepQualifiedClassNamePattern, T> onClass) {
      return onClass.apply(type);
    }

    @Override
    public boolean equals(Object o) {
      if (this == o) {
        return true;
      }
      if (!(o instanceof ClassType)) {
        return false;
      }
      ClassType classType = (ClassType) o;
      return Objects.equals(type, classType.type);
    }

    @Override
    public int hashCode() {
      return Objects.hash(type);
    }

    @Override
    public String toString() {
      return type.toString();
    }
  }

  private static class ArrayType extends KeepTypePattern {
    private final KeepArrayTypePattern type;

    public ArrayType(KeepArrayTypePattern type) {
      this.type = type;
    }

    @Override
    public <T> T apply(
        Supplier<T> onAny,
        Function<KeepPrimitiveTypePattern, T> onPrimitive,
        Function<KeepArrayTypePattern, T> onArray,
        Function<KeepQualifiedClassNamePattern, T> onClass) {
      return onArray.apply(type);
    }

    @Override
    public boolean equals(Object o) {
      if (this == o) {
        return true;
      }
      if (!(o instanceof ArrayType)) {
        return false;
      }
      ArrayType arrayType = (ArrayType) o;
      return Objects.equals(type, arrayType.type);
    }

    @Override
    public int hashCode() {
      return Objects.hash(type);
    }

    @Override
    public String toString() {
      return type.toString();
    }
  }
}
