/*
 * 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.io.Opcodes;
import com.android.dx.rop.cst.Constant;
import com.android.dx.rop.cst.CstBaseMethodRef;
import com.android.dx.util.AnnotatedOutput;
import com.android.dx.util.ExceptionWithContext;
import com.android.dx.util.FixedSizeList;
import com.android.dx.util.IndentingWriter;

import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;

/**
 * List of {@link DalvInsn} instances.
 */
public final class DalvInsnList extends FixedSizeList {

    /**
     * The amount of register space, in register units, required for this
     * code block. This may be greater than the largest observed register+
     * category because the method this code block exists in may
     * specify arguments that are unused by the method.
     */
    private final int regCount;

    /**
     * Constructs and returns an immutable instance whose elements are
     * identical to the ones in the given list, in the same order.
     *
     * @param list {@code non-null;} the list to use for elements
     * @param regCount count, in register-units, of the number of registers
     * this code block requires.
     * @return {@code non-null;} an appropriately-constructed instance of this
     * class
     */
    public static DalvInsnList makeImmutable(ArrayList<DalvInsn> list,
            int regCount) {
        int size = list.size();
        DalvInsnList result = new DalvInsnList(size, regCount);

        for (int i = 0; i < size; i++) {
            result.set(i, list.get(i));
        }

        result.setImmutable();
        return result;
    }

    /**
     * Constructs an instance. All indices initially contain {@code null}.
     *
     * @param size the size of the list
     */
    public DalvInsnList(int size, int regCount) {
        super(size);
        this.regCount = regCount;
    }

    /**
     * Gets the element at the given index. It is an error to call
     * this with the index for an element which was never set; if you
     * do that, this will throw {@code NullPointerException}.
     *
     * @param n {@code >= 0, < size();} which index
     * @return {@code non-null;} element at that index
     */
    public DalvInsn get(int n) {
        return (DalvInsn) get0(n);
    }

    /**
     * Sets the instruction at the given index.
     *
     * @param n {@code >= 0, < size();} which index
     * @param insn {@code non-null;} the instruction to set at {@code n}
     */
    public void set(int n, DalvInsn insn) {
        set0(n, insn);
    }

    /**
     * Gets the size of this instance, in 16-bit code units. This will only
     * return a meaningful result if the instructions in this instance all
     * have valid addresses.
     *
     * @return {@code >= 0;} the size
     */
    public int codeSize() {
        int sz = size();

        if (sz == 0) {
            return 0;
        }

        DalvInsn last = get(sz - 1);
        return last.getNextAddress();
    }

    /**
     * Writes all the instructions in this instance to the given output
     * destination.
     *
     * @param out {@code non-null;} where to write to
     */
    public void writeTo(AnnotatedOutput out) {
        int startCursor = out.getCursor();
        int sz = size();

        if (out.annotates()) {
            boolean verbose = out.isVerbose();

            for (int i = 0; i < sz; i++) {
                DalvInsn insn = (DalvInsn) get0(i);
                int codeBytes = insn.codeSize() * 2;
                String s;

                if ((codeBytes != 0) || verbose) {
                    s = insn.listingString("  ", out.getAnnotationWidth(),
                            true);
                } else {
                    s = null;
                }

                if (s != null) {
                    out.annotate(codeBytes, s);
                } else if (codeBytes != 0) {
                    out.annotate(codeBytes, "");
                }
            }
        }

        for (int i = 0; i < sz; i++) {
            DalvInsn insn = (DalvInsn) get0(i);
            try {
                insn.writeTo(out);
            } catch (RuntimeException ex) {
                throw ExceptionWithContext.withContext(ex,
                        "...while writing " + insn);
            }
        }

        // Sanity check of the amount written.
        int written = (out.getCursor() - startCursor) / 2;
        if (written != codeSize()) {
            throw new RuntimeException("write length mismatch; expected " +
                    codeSize() + " but actually wrote " + written);
        }
    }

    /**
     * Gets the minimum required register count implied by this
     * instance.  This includes any unused parameters that could
     * potentially be at the top of the register space.
     * @return {@code >= 0;} the required registers size
     */
    public int getRegistersSize() {
        return regCount;
    }

    /**
     * Gets the size of the outgoing arguments area required by this
     * method. This is equal to the largest argument word count of any
     * method referred to by this instance.
     *
     * @return {@code >= 0;} the required outgoing arguments size
     */
    public int getOutsSize() {
        int sz = size();
        int result = 0;

        for (int i = 0; i < sz; i++) {
            DalvInsn insn = (DalvInsn) get0(i);

            if (!(insn instanceof CstInsn)) {
                continue;
            }

            Constant cst = ((CstInsn) insn).getConstant();

            if (!(cst instanceof CstBaseMethodRef)) {
                continue;
            }

            boolean isStatic =
                (insn.getOpcode().getFamily() == Opcodes.INVOKE_STATIC);
            int count =
                ((CstBaseMethodRef) cst).getParameterWordCount(isStatic);

            if (count > result) {
                result = count;
            }
        }

        return result;
    }

    /**
     * Does a human-friendly dump of this instance.
     *
     * @param out {@code non-null;} where to dump
     * @param prefix {@code non-null;} prefix to attach to each line of output
     * @param verbose whether to be verbose; verbose output includes
     * lines for zero-size instructions and explicit constant pool indices
     */
    public void debugPrint(Writer out, String prefix, boolean verbose) {
        IndentingWriter iw = new IndentingWriter(out, 0, prefix);
        int sz = size();

        try {
            for (int i = 0; i < sz; i++) {
                DalvInsn insn = (DalvInsn) get0(i);
                String s;

                if ((insn.codeSize() != 0) || verbose) {
                    s = insn.listingString("", 0, verbose);
                } else {
                    s = null;
                }

                if (s != null) {
                    iw.write(s);
                }
            }

            iw.flush();
        } catch (IOException ex) {
            throw new RuntimeException(ex);
        }
    }

    /**
     * Does a human-friendly dump of this instance.
     *
     * @param out {@code non-null;} where to dump
     * @param prefix {@code non-null;} prefix to attach to each line of output
     * @param verbose whether to be verbose; verbose output includes
     * lines for zero-size instructions
     */
    public void debugPrint(OutputStream out, String prefix, boolean verbose) {
        Writer w = new OutputStreamWriter(out);
        debugPrint(w, prefix, verbose);

        try {
            w.flush();
        } catch (IOException ex) {
            throw new RuntimeException(ex);
        }
    }
}
