// Copyright (c) 2017, 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.dex;

import com.android.tools.r8.code.Const4;
import com.android.tools.r8.code.ConstString;
import com.android.tools.r8.code.Goto32;
import com.android.tools.r8.code.IfEq;
import com.android.tools.r8.code.IfEqz;
import com.android.tools.r8.code.IfNe;
import com.android.tools.r8.code.IfNez;
import com.android.tools.r8.code.Instruction;
import com.android.tools.r8.code.ReturnVoid;
import com.android.tools.r8.graph.DexCode;
import com.android.tools.r8.graph.DexCode.Try;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.MethodAccessFlags;
import com.android.tools.r8.naming.NamingLens;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;

public class JumboStringProcessing {

  @Test
  public void branching() {
    DexItemFactory factory = new DexItemFactory();
    DexString string = factory.createString("turn into jumbo");
    factory.sort(NamingLens.getIdentityLens());
    Instruction[] instructions = buildInstructions(string, false);
    DexCode code = jumboStringProcess(factory, string, instructions);
    Instruction[] rewrittenInstructions = code.instructions;
    assert rewrittenInstructions[1] instanceof IfEq;
    IfEq condition = (IfEq) rewrittenInstructions[1];
    assert condition.getOffset() + condition.CCCC == rewrittenInstructions[3].getOffset();
    assert rewrittenInstructions[2] instanceof Goto32;
    Goto32 jump = (Goto32) rewrittenInstructions[2];
    Instruction lastInstruction = rewrittenInstructions[rewrittenInstructions.length - 1];
    assert jump.getOffset() + jump.AAAAAAAA == lastInstruction.getOffset();
  }

  @Test
  public void branching2() {
    DexItemFactory factory = new DexItemFactory();
    DexString string = factory.createString("turn into jumbo");
    factory.sort(NamingLens.getIdentityLens());
    Instruction[] instructions = buildInstructions(string, true);
    DexCode code = jumboStringProcess(factory, string, instructions);
    Instruction[] rewrittenInstructions = code.instructions;
    assert rewrittenInstructions[1] instanceof IfEqz;
    IfEqz condition = (IfEqz) rewrittenInstructions[1];
    assert condition.getOffset() + condition.BBBB == rewrittenInstructions[3].getOffset();
    assert rewrittenInstructions[2] instanceof Goto32;
    Goto32 jump = (Goto32) rewrittenInstructions[2];
    Instruction lastInstruction = rewrittenInstructions[rewrittenInstructions.length - 1];
    assert jump.getOffset() + jump.AAAAAAAA == lastInstruction.getOffset();
  }

  private Instruction[] buildInstructions(DexString string, boolean zeroCondition) {
    List<Instruction> instructions = new ArrayList<>();
    int offset = 0;
    Instruction instr = new Const4(0, 0);
    instr.setOffset(offset);
    instructions.add(instr);
    offset += instr.getSize();
    int lastInstructionOffset = 15000 * 2 + 2 + offset;
    if (zeroCondition) {
      instr = new IfNez(0, lastInstructionOffset - offset);
    } else {
      instr = new IfNe(0, 0, lastInstructionOffset - offset);
    }
    instr.setOffset(offset);
    instructions.add(instr);
    offset += instr.getSize();
    for (int i = 0; i < 15000; i++) {
      instr = new ConstString(0, string);
      instr.setOffset(offset);
      instructions.add(instr);
      offset += instr.getSize();
    }
    instr = new ReturnVoid();
    instr.setOffset(offset);
    instructions.add(instr);
    assert instr.getOffset() == lastInstructionOffset;
    return instructions.toArray(new Instruction[instructions.size()]);
  }

  private DexCode jumboStringProcess(
      DexItemFactory factory, DexString string, Instruction[] instructions) {
    DexCode code = new DexCode(
        1,
        0,
        0,
        instructions,
        new Try[0],
        null,
        null,
        null);
    MethodAccessFlags flags = MethodAccessFlags.fromSharedAccessFlags(Constants.ACC_PUBLIC, false);
    DexEncodedMethod method = new DexEncodedMethod(null, flags, null, null, code);
    new JumboStringRewriter(method, string, factory).rewrite();
    return method.getCode().asDexCode();
  }
}
