/*
 * 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.rop.annotation.Annotations;
import com.android.dx.rop.annotation.Annotation;
import com.android.dx.util.AnnotatedOutput;
import com.android.dx.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);
        }
    }
}
