/*
 * 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.file;

import com.android.dx.dex.code.DalvCode;
import com.android.dx.dex.code.DalvInsnList;
import com.android.dx.dex.code.LocalList;
import com.android.dx.dex.code.PositionList;
import com.android.dx.rop.cst.CstMethodRef;
import com.android.dx.util.AnnotatedOutput;
import com.android.dx.util.ExceptionWithContext;

import java.io.PrintWriter;

public class DebugInfoItem extends OffsettedItem {
    /** the required alignment for instances of this class */
    private static final int ALIGNMENT = 1;

    private static final boolean ENABLE_ENCODER_SELF_CHECK = false;

    /** {@code non-null;} the code this item represents */
    private final DalvCode code;

    private byte[] encoded;

    private final boolean isStatic;
    private final CstMethodRef ref;

    public DebugInfoItem(DalvCode code, boolean isStatic, CstMethodRef ref) {
        // We don't know the write size yet.
        super (ALIGNMENT, -1);

        if (code == null) {
            throw new NullPointerException("code == null");
        }

        this.code = code;
        this.isStatic = isStatic;
        this.ref = ref;
    }

    /** {@inheritDoc} */
    @Override
    public ItemType itemType() {
        return ItemType.TYPE_DEBUG_INFO_ITEM;
    }

    /** {@inheritDoc} */
    @Override
    public void addContents(DexFile file) {
        // No contents to add.
    }

    /** {@inheritDoc} */
    @Override
    protected void place0(Section addedTo, int offset) {
        // Encode the data and note the size.

        try {
            encoded = encode(addedTo.getFile(), null, null, null, false);
            setWriteSize(encoded.length);
        } catch (RuntimeException ex) {
            throw ExceptionWithContext.withContext(ex,
                    "...while placing debug info for " + ref.toHuman());
        }
    }

    /** {@inheritDoc} */
    @Override
    public String toHuman() {
        throw new RuntimeException("unsupported");
    }

    /**
     * Writes annotations for the elements of this list, as
     * zero-length. This is meant to be used for dumping this instance
     * directly after a code dump (with the real local list actually
     * existing elsewhere in the output).
     *
     * @param file {@code non-null;} the file to use for referencing other sections
     * @param out {@code non-null;} where to annotate to
     * @param prefix {@code null-ok;} prefix to attach to each line of output
     */
    public void annotateTo(DexFile file, AnnotatedOutput out, String prefix) {
        encode(file, prefix, null, out, false);
    }

    /**
     * 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
     */
    public void debugPrint(PrintWriter out, String prefix) {
        encode(null, prefix, out, null, false);
    }

    /** {@inheritDoc} */
    @Override
    protected void writeTo0(DexFile file, AnnotatedOutput out) {
        if (out.annotates()) {
            /*
             * Re-run the encoder to generate the annotations,
             * but write the bits from the original encode
             */

            out.annotate(offsetString() + " debug info");
            encode(file, null, null, out, true);
        }

        out.write(encoded);
    }

    /**
     * Performs debug info encoding.
     *
     * @param file {@code null-ok;} file to refer to during encoding
     * @param prefix {@code null-ok;} prefix to attach to each line of output
     * @param debugPrint {@code null-ok;} if specified, an alternate output for
     * annotations
     * @param out {@code null-ok;} if specified, where annotations should go
     * @param consume whether to claim to have consumed output for
     * {@code out}
     * @return {@code non-null;} the encoded array
     */
    private byte[] encode(DexFile file, String prefix, PrintWriter debugPrint,
            AnnotatedOutput out, boolean consume) {
        byte[] result = encode0(file, prefix, debugPrint, out, consume);

        if (ENABLE_ENCODER_SELF_CHECK && (file != null)) {
            try {
                DebugInfoDecoder.validateEncode(result, file, ref, code,
                        isStatic);
            } catch (RuntimeException ex) {
                // Reconvert, annotating to System.err.
                encode0(file, "", new PrintWriter(System.err, true), null,
                        false);
                throw ex;
            }
        }

        return result;
    }

    /**
     * Helper for {@link #encode} to do most of the work.
     *
     * @param file {@code null-ok;} file to refer to during encoding
     * @param prefix {@code null-ok;} prefix to attach to each line of output
     * @param debugPrint {@code null-ok;} if specified, an alternate output for
     * annotations
     * @param out {@code null-ok;} if specified, where annotations should go
     * @param consume whether to claim to have consumed output for
     * {@code out}
     * @return {@code non-null;} the encoded array
     */
    private byte[] encode0(DexFile file, String prefix, PrintWriter debugPrint,
            AnnotatedOutput out, boolean consume) {
        PositionList positions = code.getPositions();
        LocalList locals = code.getLocals();
        DalvInsnList insns = code.getInsns();
        int codeSize = insns.codeSize();
        int regSize = insns.getRegistersSize();

        DebugInfoEncoder encoder =
            new DebugInfoEncoder(positions, locals,
                    file, codeSize, regSize, isStatic, ref);

        byte[] result;

        if ((debugPrint == null) && (out == null)) {
            result = encoder.convert();
        } else {
            result = encoder.convertAndAnnotate(prefix, debugPrint, out,
                    consume);
        }

        return result;
    }
}
