/*
 * Copyright (C) 2008 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.CatchHandlerList;
import com.android.dx.dex.code.CatchTable;
import com.android.dx.dex.code.DalvCode;
import com.android.dx.util.AnnotatedOutput;
import com.android.dx.util.ByteArrayAnnotatedOutput;
import com.android.dx.util.Hex;
import java.io.PrintWriter;
import java.util.Map;
import java.util.TreeMap;

/**
 * List of exception handlers (tuples of covered range, catch type,
 * handler address) for a particular piece of code. Instances of this
 * class correspond to a {@code try_item[]} and a
 * {@code catch_handler_item[]}.
 */
public final class CatchStructs {
    /**
     * the size of a {@code try_item}: a {@code uint}
     * and two {@code ushort}s
     */
    private static final int TRY_ITEM_WRITE_SIZE = 4 + (2 * 2);

    /** {@code non-null;} code that contains the catches */
    private final DalvCode code;

    /**
     * {@code null-ok;} the underlying table; set in
     * {@link #finishProcessingIfNecessary}
     */
    private CatchTable table;

    /**
     * {@code null-ok;} the encoded handler list, if calculated; set in
     * {@link #encode}
     */
    private byte[] encodedHandlers;

    /**
     * length of the handlers header (encoded size), if known; used for
     * annotation
     */
    private int encodedHandlerHeaderSize;

    /**
     * {@code null-ok;} map from handler lists to byte offsets, if calculated; set in
     * {@link #encode}
     */
    private TreeMap<CatchHandlerList, Integer> handlerOffsets;

    /**
     * Constructs an instance.
     *
     * @param code {@code non-null;} code that contains the catches
     */
    public CatchStructs(DalvCode code) {
        this.code = code;
        this.table = null;
        this.encodedHandlers = null;
        this.encodedHandlerHeaderSize = 0;
        this.handlerOffsets = null;
    }

    /**
     * Finish processing the catches, if necessary.
     */
    private void finishProcessingIfNecessary() {
        if (table == null) {
            table = code.getCatches();
        }
    }

    /**
     * Gets the size of the tries list, in entries.
     *
     * @return {@code >= 0;} the tries list size
     */
    public int triesSize() {
        finishProcessingIfNecessary();
        return table.size();
    }

    /**
     * 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) {
        annotateEntries(prefix, out, null);
    }

    /**
     * Encodes the handler lists.
     *
     * @param file {@code non-null;} file this instance is part of
     */
    public void encode(DexFile file) {
        finishProcessingIfNecessary();

        TypeIdsSection typeIds = file.getTypeIds();
        int size = table.size();

        handlerOffsets = new TreeMap<CatchHandlerList, Integer>();

        /*
         * First add a map entry for each unique list. The tree structure
         * will ensure they are sorted when we reiterate later.
         */
        for (int i = 0; i < size; i++) {
            handlerOffsets.put(table.get(i).getHandlers(), null);
        }

        if (handlerOffsets.size() > 65535) {
            throw new UnsupportedOperationException(
                    "too many catch handlers");
        }

        ByteArrayAnnotatedOutput out = new ByteArrayAnnotatedOutput();

        // Write out the handlers "header" consisting of its size in entries.
        encodedHandlerHeaderSize =
            out.writeUleb128(handlerOffsets.size());

        // Now write the lists out in order, noting the offset of each.
        for (Map.Entry<CatchHandlerList, Integer> mapping :
                 handlerOffsets.entrySet()) {
            CatchHandlerList list = mapping.getKey();
            int listSize = list.size();
            boolean catchesAll = list.catchesAll();

            // Set the offset before we do any writing.
            mapping.setValue(out.getCursor());

            if (catchesAll) {
                // A size <= 0 means that the list ends with a catch-all.
                out.writeSleb128(-(listSize - 1));
                listSize--;
            } else {
                out.writeSleb128(listSize);
            }

            for (int i = 0; i < listSize; i++) {
                CatchHandlerList.Entry entry = list.get(i);
                out.writeUleb128(
                        typeIds.indexOf(entry.getExceptionType()));
                out.writeUleb128(entry.getHandler());
            }

            if (catchesAll) {
                out.writeUleb128(list.get(listSize).getHandler());
            }
        }

        encodedHandlers = out.toByteArray();
    }

    /**
     * Gets the write size of this instance, in bytes.
     *
     * @return {@code >= 0;} the write size
     */
    public int writeSize() {
        return (triesSize() * TRY_ITEM_WRITE_SIZE) +
                + encodedHandlers.length;
    }

    /**
     * Writes this instance to the given stream.
     *
     * @param file {@code non-null;} file this instance is part of
     * @param out {@code non-null;} where to write to
     */
    public void writeTo(DexFile file, AnnotatedOutput out) {
        finishProcessingIfNecessary();

        if (out.annotates()) {
            annotateEntries("  ", null, out);
        }

        int tableSize = table.size();
        for (int i = 0; i < tableSize; i++) {
            CatchTable.Entry one = table.get(i);
            int start = one.getStart();
            int end = one.getEnd();
            int insnCount = end - start;

            if (insnCount >= 65536) {
                throw new UnsupportedOperationException(
                        "bogus exception range: " + Hex.u4(start) + ".." +
                        Hex.u4(end));
            }

            out.writeInt(start);
            out.writeShort(insnCount);
            out.writeShort(handlerOffsets.get(one.getHandlers()));
        }

        out.write(encodedHandlers);
    }

    /**
     * Helper method to annotate or simply print the exception handlers.
     * Only one of {@code printTo} or {@code annotateTo} should
     * be non-null.
     *
     * @param prefix {@code non-null;} prefix for each line
     * @param printTo {@code null-ok;} where to print to
     * @param annotateTo {@code null-ok;} where to consume bytes and annotate to
     */
    private void annotateEntries(String prefix, PrintWriter printTo,
            AnnotatedOutput annotateTo) {
        finishProcessingIfNecessary();

        boolean consume = (annotateTo != null);
        int amt1 = consume ? 6 : 0;
        int amt2 = consume ? 2 : 0;
        int size = table.size();
        String subPrefix = prefix + "  ";

        if (consume) {
            annotateTo.annotate(0, prefix + "tries:");
        } else {
            printTo.println(prefix + "tries:");
        }

        for (int i = 0; i < size; i++) {
            CatchTable.Entry entry = table.get(i);
            CatchHandlerList handlers = entry.getHandlers();
            String s1 = subPrefix + "try " + Hex.u2or4(entry.getStart())
                + ".." + Hex.u2or4(entry.getEnd());
            String s2 = handlers.toHuman(subPrefix, "");

            if (consume) {
                annotateTo.annotate(amt1, s1);
                annotateTo.annotate(amt2, s2);
            } else {
                printTo.println(s1);
                printTo.println(s2);
            }
        }

        if (! consume) {
            // Only emit the handler lists if we are consuming bytes.
            return;
        }

        annotateTo.annotate(0, prefix + "handlers:");
        annotateTo.annotate(encodedHandlerHeaderSize,
                subPrefix + "size: " + Hex.u2(handlerOffsets.size()));

        int lastOffset = 0;
        CatchHandlerList lastList = null;

        for (Map.Entry<CatchHandlerList, Integer> mapping :
                 handlerOffsets.entrySet()) {
            CatchHandlerList list = mapping.getKey();
            int offset = mapping.getValue();

            if (lastList != null) {
                annotateAndConsumeHandlers(lastList, lastOffset,
                        offset - lastOffset, subPrefix, printTo, annotateTo);
            }

            lastList = list;
            lastOffset = offset;
        }

        annotateAndConsumeHandlers(lastList, lastOffset,
                encodedHandlers.length - lastOffset,
                subPrefix, printTo, annotateTo);
    }

    /**
     * Helper for {@link #annotateEntries} to annotate a catch handler list
     * while consuming it.
     *
     * @param handlers {@code non-null;} handlers to annotate
     * @param offset {@code >= 0;} the offset of this handler
     * @param size {@code >= 1;} the number of bytes the handlers consume
     * @param prefix {@code non-null;} prefix for each line
     * @param printTo {@code null-ok;} where to print to
     * @param annotateTo {@code non-null;} where to annotate to
     */
    private static void annotateAndConsumeHandlers(CatchHandlerList handlers,
            int offset, int size, String prefix, PrintWriter printTo,
            AnnotatedOutput annotateTo) {
        String s = handlers.toHuman(prefix, Hex.u2(offset) + ": ");

        if (printTo != null) {
            printTo.println(s);
        }

        annotateTo.annotate(size, s);
    }
}
