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

import com.android.dexgen.rop.annotation.Annotation;
import com.android.dexgen.rop.annotation.Annotations;
import com.android.dexgen.util.AnnotatedOutput;
import com.android.dexgen.util.Hex;

/**
 * Set of annotations, where no annotation type appears more than once.
 */
public final class AnnotationSetItem extends OffsettedItem {
    /** the required alignment for instances of this class */
    private static final int ALIGNMENT = 4;

    /** the size of an entry int the set: one {@code uint} */
    private static final int ENTRY_WRITE_SIZE = 4;

    /** {@code non-null;} the set of annotations */
    private final Annotations annotations;

    /**
     * {@code non-null;} set of annotations as individual items in an array.
     * <b>Note:</b> The contents have to get sorted by type id before
     * writing.
     */
    private final AnnotationItem[] items;

    /**
     * Constructs an instance.
     *
     * @param annotations {@code non-null;} set of annotations
     */
    public AnnotationSetItem(Annotations annotations) {
        super(ALIGNMENT, writeSize(annotations));

        this.annotations = annotations;
        this.items = new AnnotationItem[annotations.size()];

        int at = 0;
        for (Annotation a : annotations.getAnnotations()) {
            items[at] = new AnnotationItem(a);
            at++;
        }
    }

    /**
     * Gets the write size for the given set.
     *
     * @param annotations {@code non-null;} the set
     * @return {@code > 0;} the write size
     */
    private static int writeSize(Annotations annotations) {
        // This includes an int size at the start of the list.

        try {
            return (annotations.size() * ENTRY_WRITE_SIZE) + 4;
        } catch (NullPointerException ex) {
            // Elucidate the exception.
            throw new NullPointerException("list == null");
        }
    }

    /**
     * Gets the underlying annotations of this instance
     *
     * @return {@code non-null;} the annotations
     */
    public Annotations getAnnotations() {
        return annotations;
    }

    /** {@inheritDoc} */
    @Override
    public int hashCode() {
        return annotations.hashCode();
    }

    /** {@inheritDoc} */
    @Override
    protected int compareTo0(OffsettedItem other) {
        AnnotationSetItem otherSet = (AnnotationSetItem) other;

        return annotations.compareTo(otherSet.annotations);
    }

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

    /** {@inheritDoc} */
    @Override
    public String toHuman() {
        return annotations.toString();
    }

    /** {@inheritDoc} */
    public void addContents(DexFile file) {
        MixedItemSection byteData = file.getByteData();
        int size = items.length;

        for (int i = 0; i < size; i++) {
            items[i] = byteData.intern(items[i]);
        }
    }

    /** {@inheritDoc} */
    @Override
    protected void place0(Section addedTo, int offset) {
        // Sort the array to be in type id index order.
        AnnotationItem.sortByTypeIdIndex(items);
    }

    /** {@inheritDoc} */
    @Override
    protected void writeTo0(DexFile file, AnnotatedOutput out) {
        boolean annotates = out.annotates();
        int size = items.length;

        if (annotates) {
            out.annotate(0, offsetString() + " annotation set");
            out.annotate(4, "  size: " + Hex.u4(size));
        }

        out.writeInt(size);

        for (int i = 0; i < size; i++) {
            AnnotationItem item = items[i];
            int offset = item.getAbsoluteOffset();

            if (annotates) {
                out.annotate(4, "  entries[" + Integer.toHexString(i) + "]: " +
                        Hex.u4(offset));
                items[i].annotateTo(out, "    ");
            }

            out.writeInt(offset);
        }
    }
}
