/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.dx.dex.code;

import com.android.dx.dex.DexOptions;

import java.util.ArrayList;

/**
 * Destination for {@link DalvInsn} instances being output. This class
 * receives and collects instructions in two pieces &mdash; a primary
 * list and a suffix (generally consisting of adjunct data referred to
 * by the primary list, such as switch case tables) &mdash; which it
 * merges and emits back out in the form of a {@link DalvInsnList}
 * instance.
 */
public final class OutputCollector {
    /**
     * {@code non-null;} the associated finisher (which holds the instruction
     * list in-progress)
     */
    private final OutputFinisher finisher;

    /**
     * {@code null-ok;} suffix for the output, or {@code null} if the suffix
     * has been appended to the main output (by {@link #appendSuffixToOutput})
     */
    private ArrayList<DalvInsn> suffix;

    /**
     * Constructs an instance.
     *
     * @param dexOptions {@code non-null;} options for dex output
     * @param initialCapacity {@code >= 0;} initial capacity of the output list
     * @param suffixInitialCapacity {@code >= 0;} initial capacity of the output
     * suffix
     * @param regCount {@code >= 0;} register count for the method
     */
    public OutputCollector(DexOptions dexOptions, int initialCapacity, int suffixInitialCapacity,
            int regCount) {
        this.finisher = new OutputFinisher(dexOptions, initialCapacity, regCount);
        this.suffix = new ArrayList<DalvInsn>(suffixInitialCapacity);
    }

    /**
     * Adds an instruction to the output.
     *
     * @param insn {@code non-null;} the instruction to add
     */
    public void add(DalvInsn insn) {
        finisher.add(insn);
    }

    /**
     * Reverses a branch which is buried a given number of instructions
     * backward in the output. It is illegal to call this unless the
     * indicated instruction really is a reversible branch.
     *
     * @param which how many instructions back to find the branch;
     * {@code 0} is the most recently added instruction,
     * {@code 1} is the instruction before that, etc.
     * @param newTarget {@code non-null;} the new target for the reversed branch
     */
    public void reverseBranch(int which, CodeAddress newTarget) {
        finisher.reverseBranch(which, newTarget);
    }

    /**
     * Adds an instruction to the output suffix.
     *
     * @param insn {@code non-null;} the instruction to add
     */
    public void addSuffix(DalvInsn insn) {
        suffix.add(insn);
    }

    /**
     * Gets the results of all the calls on this instance, in the form of
     * an {@link OutputFinisher}.
     *
     * @return {@code non-null;} the output finisher
     * @throws UnsupportedOperationException if this method has
     * already been called
     */
    public OutputFinisher getFinisher() {
        if (suffix == null) {
            throw new UnsupportedOperationException("already processed");
        }

        appendSuffixToOutput();
        return finisher;
    }

    /**
     * Helper for {@link #getFinisher}, which appends the suffix to
     * the primary output.
     */
    private void appendSuffixToOutput() {
        int size = suffix.size();

        for (int i = 0; i < size; i++) {
            finisher.add(suffix.get(i));
        }

        suffix = null;
    }
}
