// 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.utils.structural.StructuralItem.CompareToAccept;
import com.android.tools.r8.utils.structural.StructuralItem.HashingAccept;
import java.util.Comparator;
import java.util.Iterator;
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;

/** Base class to share most visiting methods */
public abstract class CompareToVisitorBase extends CompareToVisitor {

  private int order = 0;

  public final boolean stillEqual() {
    return order == 0;
  }

  public final int getOrder() {
    return order;
  }

  public final void setOrder(int order) {
    this.order = order;
  }

  @Override
  public final void visitBool(boolean value1, boolean value2) {
    if (stillEqual()) {
      setOrder(Boolean.compare(value1, value2));
    }
  }

  @Override
  public final void visitInt(int value1, int value2) {
    if (stillEqual()) {
      setOrder(Integer.compare(value1, value2));
    }
  }

  @Override
  public void visitLong(long value1, long value2) {
    if (stillEqual()) {
      setOrder(Long.compare(value1, value2));
    }
  }

  @Override
  public void visitFloat(float value1, float value2) {
    if (stillEqual()) {
      setOrder(Float.compare(value1, value2));
    }
  }

  @Override
  public void visitDouble(double value1, double value2) {
    if (stillEqual()) {
      setOrder(Double.compare(value1, value2));
    }
  }

  @Override
  public <S> void visitItemIterator(
      Iterator<S> it1, Iterator<S> it2, CompareToAccept<S> compareToAccept) {
    while (stillEqual() && it1.hasNext() && it2.hasNext()) {
      compareToAccept.acceptCompareTo(it1.next(), it2.next(), this);
    }
    if (stillEqual()) {
      visitBool(it1.hasNext(), it2.hasNext());
    }
  }

  @Override
  public void visitDexString(DexString string1, DexString string2) {
    if (stillEqual()) {
      setOrder(string1.compareTo(string2));
    }
  }

  @Override
  public void visitDexReference(DexReference reference1, DexReference reference2) {
    if (stillEqual()) {
      visitInt(reference1.referenceTypeOrder(), reference2.referenceTypeOrder());
      if (stillEqual()) {
        assert reference1.getClass() == reference2.getClass();
        if (reference1.isDexType()) {
          visitDexType(reference1.asDexType(), reference2.asDexType());
        } else if (reference1.isDexField()) {
          visitDexField(reference1.asDexField(), reference2.asDexField());
        } else {
          visitDexMethod(reference1.asDexMethod(), reference2.asDexMethod());
        }
      }
    }
  }

  @Override
  public final <S> void visit(S item1, S item2, Comparator<S> comparator) {
    if (stillEqual()) {
      setOrder(comparator.compare(item1, item2));
    }
  }

  @Override
  public final <S> void visit(S item1, S item2, StructuralAccept<S> accept) {
    if (stillEqual()) {
      accept.apply(new ItemSpecification<>(item1, item2, this));
    }
  }

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

    private final CompareToVisitorBase parent;
    private final T item1;
    private final T item2;

    private ItemSpecification(T item1, T item2, CompareToVisitorBase parent) {
      this.item1 = item1;
      this.item2 = item2;
      this.parent = parent;
    }

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

    @Override
    public ItemSpecification<T> withBool(Predicate<T> getter) {
      if (parent.stillEqual()) {
        parent.visitBool(getter.test(item1), getter.test(item2));
      }
      return this;
    }

    @Override
    public ItemSpecification<T> withInt(ToIntFunction<T> getter) {
      if (parent.stillEqual()) {
        parent.visitInt(getter.applyAsInt(item1), getter.applyAsInt(item2));
      }
      return this;
    }

    @Override
    public ItemSpecification<T> withLong(ToLongFunction<T> getter) {
      if (parent.stillEqual()) {
        parent.visitLong(getter.applyAsLong(item1), getter.applyAsLong(item2));
      }
      return this;
    }

    @Override
    public ItemSpecification<T> withDouble(ToDoubleFunction<T> getter) {
      if (parent.stillEqual()) {
        parent.visitDouble(getter.applyAsDouble(item1), getter.applyAsDouble(item2));
      }
      return this;
    }

    @Override
    public ItemSpecification<T> withIntArray(Function<T, int[]> getter) {
      if (parent.stillEqual()) {
        int[] is1 = getter.apply(item1);
        int[] is2 = getter.apply(item2);
        int minLength = Math.min(is1.length, is2.length);
        for (int i = 0; i < minLength && parent.stillEqual(); i++) {
          parent.visitInt(is1[i], is2[i]);
        }
        if (parent.stillEqual()) {
          parent.visitInt(is1.length, is2.length);
        }
      }
      return this;
    }

    @Override
    public <S> ItemSpecification<T> withConditionalCustomItem(
        Predicate<T> predicate,
        Function<T, S> getter,
        CompareToAccept<S> compare,
        HashingAccept<S> hasher) {
      if (parent.stillEqual()) {
        boolean test1 = predicate.test(item1);
        boolean test2 = predicate.test(item2);
        if (test1 && test2) {
          compare.acceptCompareTo(getter.apply(item1), getter.apply(item2), parent);
        } else {
          parent.visitBool(test1, test2);
        }
      }
      return this;
    }

    @Override
    protected <S> ItemSpecification<T> withItemIterator(
        Function<T, Iterator<S>> getter, CompareToAccept<S> compare, HashingAccept<S> hasher) {
      if (parent.stillEqual()) {
        parent.visitItemIterator(getter.apply(item1), getter.apply(item2), compare);
      }
      return this;
    }
  }
}
