// 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.ir.code.CatchHandlers.CatchHandler;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
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;
    }
  }

  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 List<T> getAllTargets() {
    return targets;
  }

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

  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);
  }

  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 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();
  }
}
