// Copyright (c) 2016, 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.ir.code;

import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.lens.GraphLens;
import com.android.tools.r8.ir.code.CatchHandlers.CatchHandler;
import com.android.tools.r8.utils.ListUtils;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntList;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.function.BiConsumer;

public class CatchHandlers<T> implements Iterable<CatchHandler<T>> {

  public static class CatchHandler<T> {

    public final DexType guard;
    public final T target;

    public CatchHandler(DexType guard, T target) {
      this.guard = guard;
      this.target = target;
    }

    public T getTarget() {
      return target;
    }

    public DexType getGuard() {
      return guard;
    }
  }

  private final List<DexType> guards;
  private final List<T> targets;
  private Set<T> uniqueTargets;

  public static final CatchHandlers<Integer> EMPTY_INDICES = new CatchHandlers<>();
  public static final CatchHandlers<BasicBlock> EMPTY_BASIC_BLOCK = new CatchHandlers<>();

  private CatchHandlers() {
    guards = ImmutableList.of();
    targets = ImmutableList.of();
  }

  public CatchHandlers(List<DexType> guards, List<T> targets) {
    assert !guards.isEmpty();
    assert guards.size() == targets.size();
    // Guava ImmutableList does not support null elements.
    this.guards = ImmutableList.copyOf(guards);
    this.targets = ImmutableList.copyOf(targets);
  }

  public boolean isEmpty() {
    return size() == 0;
  }

  public int size() {
    assert guards.size() == targets.size();
    return guards.size();
  }

  public List<DexType> getGuards() {
    return guards;
  }

  public DexType getGuard(int index) {
    return guards.get(index);
  }

  public List<T> getAllTargets() {
    return targets;
  }

  public Set<T> getUniqueTargets() {
    if (uniqueTargets == null) {
      uniqueTargets = ImmutableSet.copyOf(targets);
    }
    return uniqueTargets;
  }

  @SuppressWarnings("ReferenceEquality")
  public boolean hasCatchAll(DexItemFactory factory) {
    return getGuards().size() > 0
        && getGuards().get(getGuards().size() - 1) == factory.throwableType;
  }

  public CatchHandlers<T> appendGuard(DexType guard, T target) {
    assert !guards.contains(guard);
    List<DexType> newGuards = ImmutableList.<DexType>builder().addAll(guards).add(guard).build();
    List<T> newTargets = ImmutableList.<T>builder().addAll(targets).add(target).build();
    return new CatchHandlers<>(newGuards, newTargets);
  }

  @SuppressWarnings("ReferenceEquality")
  public CatchHandlers<T> removeGuard(DexType guardToBeRemoved) {
    List<DexType> newGuards = new ArrayList<>();
    List<T> newTargets = new ArrayList<>();
    forEach(
        (guard, target) -> {
          if (guard != guardToBeRemoved) {
            newGuards.add(guard);
            newTargets.add(target);
          }
        });
    return new CatchHandlers<>(newGuards, newTargets);
  }

  public CatchHandlers<T> rewriteWithLens(GraphLens graphLens, GraphLens codeLens) {
    IntList targetIndicesToRemove = new IntArrayList();
    Set<DexType> seenGuards = Sets.newIdentityHashSet();
    List<DexType> newGuards =
        ListUtils.mapOrElse(
            guards,
            (index, guard) -> {
              DexType newGuard = graphLens.lookupType(guard, codeLens);
              if (seenGuards.add(newGuard)) {
                return newGuard;
              }
              targetIndicesToRemove.add(index);
              return null;
            },
            null);
    if (newGuards == null) {
      assert targetIndicesToRemove.isEmpty();
      return this;
    }
    List<T> newTargets =
        targetIndicesToRemove.isEmpty()
            ? targets
            : ListUtils.newArrayListWithoutIndices(targets, targetIndicesToRemove);
    return new CatchHandlers<>(newGuards, newTargets);
  }

  public void forEach(BiConsumer<DexType, T> consumer) {
    for (int i = 0; i < size(); ++i) {
      consumer.accept(guards.get(i), targets.get(i));
    }
  }

  @Override
  public Iterator<CatchHandler<T>> iterator() {
    return new Iterator<CatchHandler<T>>() {

      private int nextIndex = 0;

      @Override
      public boolean hasNext() {
        return nextIndex < size();
      }

      @Override
      public CatchHandler<T> next() {
        DexType guard = guards.get(nextIndex);
        T target = targets.get(nextIndex);
        ++nextIndex;
        return new CatchHandler<>(guard, target);
      }
    };
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }
    if (!(o instanceof CatchHandlers)) {
      return false;
    }
    CatchHandlers<?> that = (CatchHandlers<?>) o;
    return guards.equals(that.guards) && targets.equals(that.targets);
  }

  @Override
  public int hashCode() {
    return 31 * guards.hashCode() + targets.hashCode();
  }
}
