// 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.utils.structural;

import com.android.tools.r8.graph.DexReference;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.utils.structural.StructuralItem.CompareToAccept;
import com.android.tools.r8.utils.structural.StructuralItem.HashingAccept;
import com.google.common.hash.Hasher;
import java.util.Iterator;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.ToDoubleFunction;
import java.util.function.ToIntFunction;
import java.util.function.ToLongFunction;

/** Visitor for hashing a structural item under some assumed type equivalence. */
public class HashingVisitorWithTypeEquivalence extends HashingVisitor {

  public static <T> void run(
      T item, Hasher hasher, RepresentativeMap map, StructuralMapping<T> accept) {
    run(item, hasher, map, (i, visitor) -> visitor.visit(i, accept));
  }

  public static <T> void run(
      T item, Hasher hasher, RepresentativeMap map, HashingAccept<T> hashingAccept) {
    hashingAccept.acceptHashing(item, new HashingVisitorWithTypeEquivalence(hasher, map));
  }

  private final Hasher hash;
  private final RepresentativeMap representatives;

  private HashingVisitorWithTypeEquivalence(Hasher hash, RepresentativeMap representatives) {
    this.hash = hash;
    this.representatives = representatives;
  }

  @Override
  public void visitBool(boolean value) {
    hash.putBoolean(value);
  }

  @Override
  public void visitInt(int value) {
    hash.putInt(value);
  }

  @Override
  public void visitFloat(float value) {
    hash.putFloat(value);
  }

  @Override
  public void visitLong(long value) {
    hash.putLong(value);
  }

  @Override
  public void visitDouble(double value) {
    hash.putDouble(value);
  }

  @Override
  public void visitDexString(DexString string) {
    visitInt(string.hashCode());
  }

  @Override
  public void visitDexType(DexType type) {
    visitDexString(representatives.getRepresentative(type).getDescriptor());
  }

  @Override
  public <S> void visit(S item, StructuralMapping<S> accept) {
    accept.apply(new ItemSpecification<>(item, this));
  }

  @Override
  protected <S> void visitItemIterator(Iterator<S> it, HashingAccept<S> hashingAccept) {
    while (it.hasNext()) {
      hashingAccept.acceptHashing(it.next(), this);
    }
  }

  @Override
  public <S> void visit(S item, BiConsumer<S, Hasher> hasher) {
    hasher.accept(item, hash);
  }

  private static class ItemSpecification<T>
      extends StructuralSpecification<T, ItemSpecification<T>> {

    private final HashingVisitorWithTypeEquivalence parent;
    private final T item;

    private ItemSpecification(T item, HashingVisitorWithTypeEquivalence parent) {
      this.item = item;
      this.parent = parent;
    }

    @Override
    ItemSpecification<T> self() {
      return this;
    }

    @Override
    public ItemSpecification<T> withAssert(Predicate<T> predicate) {
      assert predicate.test(item);
      return this;
    }

    @Override
    public ItemSpecification<T> withBool(Predicate<T> getter) {
      parent.visitBool(getter.test(item));
      return this;
    }

    @Override
    public ItemSpecification<T> withInt(ToIntFunction<T> getter) {
      parent.visitInt(getter.applyAsInt(item));
      return this;
    }

    @Override
    public ItemSpecification<T> withLong(ToLongFunction<T> getter) {
      parent.visitLong(getter.applyAsLong(item));
      return this;
    }

    @Override
    public ItemSpecification<T> withDouble(ToDoubleFunction<T> getter) {
      parent.visitDouble(getter.applyAsDouble(item));
      return this;
    }

    @Override
    public ItemSpecification<T> withIntArray(Function<T, int[]> getter) {
      int[] ints = getter.apply(item);
      for (int i = 0; i < ints.length; i++) {
        parent.visitInt(ints[i]);
      }
      return this;
    }

    @Override
    public ItemSpecification<T> withShortArray(Function<T, short[]> getter) {
      short[] ints = getter.apply(item);
      for (int i = 0; i < ints.length; i++) {
        parent.visitInt(ints[i]);
      }
      return this;
    }

    @Override
    protected <S> ItemSpecification<T> withConditionalCustomItem(
        Predicate<T> predicate,
        Function<T, S> getter,
        CompareToAccept<S> compare,
        HashingAccept<S> hasher) {
      boolean test = predicate.test(item);
      // Always hash the predicate result to distinguish, eg, {null, null} and {null}.
      parent.visitBool(test);
      if (test) {
        hasher.acceptHashing(getter.apply(item), parent);
      }
      return this;
    }

    @Override
    protected <S> ItemSpecification<T> withCustomItemIterator(
        Function<T, Iterator<S>> getter, CompareToAccept<S> compare, HashingAccept<S> hasher) {
      parent.visitItemIterator(getter.apply(item), hasher);
      return this;
    }

    @Override
    public ItemSpecification<T> withDexReference(Function<T, DexReference> getter) {
      parent.visitDexReference(getter.apply(item));
      return this;
    }
  }
}
