// 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 static com.android.tools.r8.dex.Constants.U4BIT_MAX;
import static com.android.tools.r8.dex.Constants.U8BIT_MAX;

import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.utils.CfgPrinter;
import java.util.List;

public class If extends JumpInstruction {

  public enum Type {
    EQ, GE, GT, LE, LT, NE;

    // Returns the comparison type if the operands are swapped.
    public Type forSwappedOperands() {
      switch (this) {
        case EQ:
        case NE:
          return this;
        case GE:
          return Type.LE;
        case GT:
          return Type.LT;
        case LE:
          return Type.GE;
        case LT:
          return Type.GT;
        default:
          throw new Unreachable("Unknown if condition type.");
      }
    }

    public Type inverted() {
      switch (this) {
        case EQ:
          return Type.NE;
        case GE:
          return Type.LT;
        case GT:
          return Type.LE;
        case LE:
          return Type.GT;
        case LT:
          return Type.GE;
        case NE:
          return Type.EQ;
        default:
          throw new Unreachable("Unknown if condition type.");
      }
    }
  }

  private Type type;

  public If(Type type, Value value) {
    super(null, value);
    this.type = type;
  }

  public If(Type type, List<Value> values) {
    super(null, values);
    this.type = type;
  }

  public boolean isZeroTest() {
    return inValues.size() == 1;
  }

  public Type getType() {
    return type;
  }

  public void invert() {
    BasicBlock tmp = getTrueTarget();
    setTrueTarget(fallthroughBlock());
    setFallthroughBlock(tmp);
    type = type.inverted();
  }

  public BasicBlock getTrueTarget() {
    assert getBlock().exit() == this;
    List<BasicBlock> successors = getBlock().getSuccessors();
    assert successors.size() >= 2;
    return successors.get(successors.size() - 2);
  }

  public void setTrueTarget(BasicBlock block) {
    assert getBlock().exit() == this;
    List<BasicBlock> successors = getBlock().getSuccessors();
    assert successors.size() >= 2;
    successors.set(successors.size() - 2, block);
  }

  @Override
  public BasicBlock fallthroughBlock() {
    assert getBlock().exit() == this;
    List<BasicBlock> successors = getBlock().getSuccessors();
    assert successors.size() >= 2;
    return successors.get(successors.size() - 1);
  }

  @Override
  public void setFallthroughBlock(BasicBlock block) {
    List<BasicBlock> successors = getBlock().getSuccessors();
    successors.set(successors.size() - 1, block);
  }

  @Override
  public void buildDex(DexBuilder builder) {
    builder.addIf(this);
  }

  @Override
  public String toString() {
    return super.toString() + " " + type + " block " + getTrueTarget().getNumber()
        + " (fallthrough " + fallthroughBlock().getNumber() + ")";
  }

  @Override
  public int maxInValueRegister() {
    return isZeroTest() ? U8BIT_MAX : U4BIT_MAX;
  }

  @Override
  public int maxOutValueRegister() {
    assert false : "If instructions define no values.";
    return 0;
  }

  @Override
  public void print(CfgPrinter printer) {
    super.print(printer);
    printer.append(" B").append(getTrueTarget().getNumber());
  }

  @Override
  public boolean identicalNonValueParts(Instruction other) {
    If o = other.asIf();
    return o.getTrueTarget() == getTrueTarget()
        && o.fallthroughBlock() == fallthroughBlock()
        && o.type == type;
  }

  @Override
  public int compareNonValueParts(Instruction other) {
    assert other.isIf();
    assert false : "Not supported";
    return 0;
  }


  public BasicBlock targetFromCondition(int cond) {
    switch (type) {
      case EQ:
        return cond == 0 ? getTrueTarget() : fallthroughBlock();
      case NE:
        return cond != 0 ? getTrueTarget() : fallthroughBlock();
      case GE:
        return cond >= 0 ? getTrueTarget() : fallthroughBlock();
      case GT:
        return cond > 0 ? getTrueTarget() : fallthroughBlock();
      case LE:
        return cond <= 0 ? getTrueTarget() : fallthroughBlock();
      case LT:
        return cond < 0 ? getTrueTarget() : fallthroughBlock();
    }
    throw new Unreachable("Unexpected condition type " + type);
  }

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

  @Override
  public If asIf() {
    return this;
  }
}
