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

import com.android.dexgen.util.AnnotatedOutput;
import com.android.dexgen.util.Hex;

import java.util.HashMap;
import java.util.List;

/**
 * Class that represents a contiguous list of uniform items. Each
 * item in the list, in particular, must have the same write size and
 * alignment.
 *
 * <p>This class inherits its alignment from its items, bumped up to
 * {@code 4} if the items have a looser alignment requirement. If
 * it is more than {@code 4}, then there will be a gap after the
 * output list size (which is four bytes) and before the first item.</p>
 *
 * @param <T> type of element contained in an instance
 */
public final class UniformListItem<T extends OffsettedItem>
        extends OffsettedItem {
    /** the size of the list header */
    private static final int HEADER_SIZE = 4;

    /** {@code non-null;} the item type */
    private final ItemType itemType;

    /** {@code non-null;} the contents */
    private final List<T> items;

    /**
     * Constructs an instance. It is illegal to modify the given list once
     * it is used to construct an instance of this class.
     *
     * @param itemType {@code non-null;} the type of the item
     * @param items {@code non-null and non-empty;} list of items to represent
     */
    public UniformListItem(ItemType itemType, List<T> items) {
        super(getAlignment(items), writeSize(items));

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

        this.items = items;
        this.itemType = itemType;
    }

    /**
     * Helper for {@link #UniformListItem}, which returns the alignment
     * requirement implied by the given list. See the header comment for
     * more details.
     *
     * @param items {@code non-null;} list of items being represented
     * @return {@code >= 4;} the alignment requirement
     */
    private static int getAlignment(List<? extends OffsettedItem> items) {
        try {
            // Since they all must have the same alignment, any one will do.
            return Math.max(HEADER_SIZE, items.get(0).getAlignment());
        } catch (IndexOutOfBoundsException ex) {
            // Translate the exception.
            throw new IllegalArgumentException("items.size() == 0");
        } catch (NullPointerException ex) {
            // Translate the exception.
            throw new NullPointerException("items == null");
        }
    }

    /**
     * Calculates the write size for the given list.
     *
     * @param items {@code non-null;} the list in question
     * @return {@code >= 0;} the write size
     */
    private static int writeSize(List<? extends OffsettedItem> items) {
        /*
         * This class assumes all included items are the same size,
         * an assumption which is verified in place0().
         */
        OffsettedItem first = items.get(0);
        return (items.size() * first.writeSize()) + getAlignment(items);
    }

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

    /** {@inheritDoc} */
    @Override
    public String toString() {
        StringBuffer sb = new StringBuffer(100);

        sb.append(getClass().getName());
        sb.append(items);

        return sb.toString();
    }

    /** {@inheritDoc} */
    @Override
    public void addContents(DexFile file) {
        for (OffsettedItem i : items) {
            i.addContents(file);
        }
    }

    /** {@inheritDoc} */
    @Override
    public final String toHuman() {
        StringBuffer sb = new StringBuffer(100);
        boolean first = true;

        sb.append("{");

        for (OffsettedItem i : items) {
            if (first) {
                first = false;
            } else {
                sb.append(", ");
            }
            sb.append(i.toHuman());
        }

        sb.append("}");
        return sb.toString();
    }

    /**
     * Gets the underlying list of items.
     *
     * @return {@code non-null;} the list
     */
    public final List<T> getItems() {
        return items;
    }

    /** {@inheritDoc} */
    @Override
    protected void place0(Section addedTo, int offset) {
        offset += headerSize();

        boolean first = true;
        int theSize = -1;
        int theAlignment = -1;

        for (OffsettedItem i : items) {
            int size = i.writeSize();
            if (first) {
                theSize = size;
                theAlignment = i.getAlignment();
                first = false;
            } else {
                if (size != theSize) {
                    throw new UnsupportedOperationException(
                            "item size mismatch");
                }
                if (i.getAlignment() != theAlignment) {
                    throw new UnsupportedOperationException(
                            "item alignment mismatch");
                }
            }

            offset = i.place(addedTo, offset) + size;
        }
    }

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

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

        out.writeInt(size);

        for (OffsettedItem i : items) {
            i.writeTo(file, out);
        }
    }

    /**
     * Get the size of the header of this list.
     *
     * @return {@code >= 0;} the header size
     */
    private int headerSize() {
        /*
         * Because of how this instance was set up, this is the same
         * as the alignment.
         */
        return getAlignment();
    }
}
