/*
 * 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.util.AnnotatedOutput;
import com.android.dx.util.ExceptionWithContext;
import com.android.dx.util.Hex;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.TreeMap;

/**
 * A section of a {@code .dex} file which consists of a sequence of
 * {@link OffsettedItem} objects, which may each be of a different concrete
 * class and/or size.
 * 
 * <b>Note:</b> It is invalid for an item in an instance of this class to
 * have a larger alignment requirement than the alignment of this instance.
 */
public final class MixedItemSection extends Section {
    static enum SortType {
        /** no sorting */
        NONE,

        /** sort by type only */
        TYPE,

        /** sort in class-major order, with instances sorted per-class */
        INSTANCE;
    };

    /** {@code non-null;} sorter which sorts instances by type */
    private static final Comparator<OffsettedItem> TYPE_SORTER =
        new Comparator<OffsettedItem>() {
        public int compare(OffsettedItem item1, OffsettedItem item2) {
            ItemType type1 = item1.itemType();
            ItemType type2 = item2.itemType();
            return type1.compareTo(type2);
        }
    };
    
    /** {@code non-null;} the items in this part */
    private final ArrayList<OffsettedItem> items;

    /** {@code non-null;} items that have been explicitly interned */
    private final HashMap<OffsettedItem, OffsettedItem> interns;

    /** {@code non-null;} how to sort the items */
    private final SortType sort;

    /**
     * {@code >= -1;} the current size of this part, in bytes, or {@code -1}
     * if not yet calculated
     */
    private int writeSize;

    /**
     * Constructs an instance. The file offset is initially unknown.
     * 
     * @param name {@code null-ok;} the name of this instance, for annotation
     * purposes
     * @param file {@code non-null;} file that this instance is part of
     * @param alignment {@code > 0;} alignment requirement for the final output;
     * must be a power of 2
     * @param sort how the items should be sorted in the final output
     */
    public MixedItemSection(String name, DexFile file, int alignment,
            SortType sort) {
        super(name, file, alignment);

        this.items = new ArrayList<OffsettedItem>(100);
        this.interns = new HashMap<OffsettedItem, OffsettedItem>(100);
        this.sort = sort;
        this.writeSize = -1;
    }

    /** {@inheritDoc} */
    @Override
    public Collection<? extends Item> items() {
        return items;
    }

    /** {@inheritDoc} */
    @Override
    public int writeSize() {
        throwIfNotPrepared();
        return writeSize;
    }

    /** {@inheritDoc} */
    @Override
    public int getAbsoluteItemOffset(Item item) {
        OffsettedItem oi = (OffsettedItem) item;
        return oi.getAbsoluteOffset();
    }

    /**
     * Gets the size of this instance, in items.
     * 
     * @return {@code >= 0;} the size
     */
    public int size() {
        return items.size();
    }

    /**
     * Writes the portion of the file header that refers to this instance.
     *
     * @param out {@code non-null;} where to write
     */
    public void writeHeaderPart(AnnotatedOutput out) {
        throwIfNotPrepared();

        if (writeSize == -1) {
            throw new RuntimeException("write size not yet set");            
        }

        int sz = writeSize;
        int offset = (sz == 0) ? 0 : getFileOffset();
        String name = getName();

        if (name == null) {
            name = "<unnamed>";
        }

        int spaceCount = 15 - name.length();
        char[] spaceArr = new char[spaceCount];
        Arrays.fill(spaceArr, ' ');
        String spaces = new String(spaceArr);

        if (out.annotates()) {
            out.annotate(4, name + "_size:" + spaces + Hex.u4(sz));
            out.annotate(4, name + "_off: " + spaces + Hex.u4(offset));
        }

        out.writeInt(sz);
        out.writeInt(offset);
    }

    /**
     * Adds an item to this instance. This will in turn tell the given item
     * that it has been added to this instance. It is invalid to add the
     * same item to more than one instance, nor to add the same items
     * multiple times to a single instance.
     * 
     * @param item {@code non-null;} the item to add
     */
    public void add(OffsettedItem item) {
        throwIfPrepared();

        try {
            if (item.getAlignment() > getAlignment()) {
                throw new IllegalArgumentException(
                        "incompatible item alignment");
            }
        } catch (NullPointerException ex) {
            // Elucidate the exception.
            throw new NullPointerException("item == null");
        }

        items.add(item);
    }

    /**
     * Interns an item in this instance, returning the interned instance
     * (which may not be the one passed in). This will add the item if no
     * equal item has been added.
     * 
     * @param item {@code non-null;} the item to intern
     * @return {@code non-null;} the equivalent interned instance
     */
    public <T extends OffsettedItem> T intern(T item) {
        throwIfPrepared();

        OffsettedItem result = interns.get(item);
        
        if (result != null) {
            return (T) result;
        }

        add(item);
        interns.put(item, item);
        return item;
    }

    /**
     * Gets an item which was previously interned.
     * 
     * @param item {@code non-null;} the item to look for
     * @return {@code non-null;} the equivalent already-interned instance
     */
    public <T extends OffsettedItem> T get(T item) {
        throwIfNotPrepared();

        OffsettedItem result = interns.get(item);
        
        if (result != null) {
            return (T) result;
        }

        throw new NoSuchElementException(item.toString());
    }

    /**
     * Writes an index of contents of the items in this instance of the
     * given type. If there are none, this writes nothing. If there are any,
     * then the index is preceded by the given intro string.
     * 
     * @param out {@code non-null;} where to write to
     * @param itemType {@code non-null;} the item type of interest
     * @param intro {@code non-null;} the introductory string for non-empty indices
     */
    public void writeIndexAnnotation(AnnotatedOutput out, ItemType itemType,
            String intro) {
        throwIfNotPrepared();

        TreeMap<String, OffsettedItem> index =
            new TreeMap<String, OffsettedItem>();

        for (OffsettedItem item : items) {
            if (item.itemType() == itemType) {
                String label = item.toHuman();
                index.put(label, item);
            }
        }

        if (index.size() == 0) {
            return;
        }

        out.annotate(0, intro);
        
        for (Map.Entry<String, OffsettedItem> entry : index.entrySet()) {
            String label = entry.getKey();
            OffsettedItem item = entry.getValue();
            out.annotate(0, item.offsetString() + ' ' + label + '\n');
        }
    }

    /** {@inheritDoc} */
    @Override
    protected void prepare0() {
        DexFile file = getFile();

        /*
         * It's okay for new items to be added as a result of an
         * addContents() call; we just have to deal with the possibility.
         */

        int i = 0;
        for (;;) {
            int sz = items.size();
            if (i >= sz) {
                break;
            }

            for (/*i*/; i < sz; i++) {
                OffsettedItem one = items.get(i);
                one.addContents(file);
            }
        }
    }

    /**
     * Places all the items in this instance at particular offsets. This
     * will call {@link OffsettedItem#place} on each item. If an item
     * does not know its write size before the call to {@code place},
     * it is that call which is responsible for setting the write size.
     * This method may only be called once per instance; subsequent calls
     * will throw an exception.
     */
    public void placeItems() {
        throwIfNotPrepared();

        switch (sort) {
            case INSTANCE: {
                Collections.sort(items);
                break;
            }
            case TYPE: {
                Collections.sort(items, TYPE_SORTER);
                break;
            }
        }

        int sz = items.size();
        int outAt = 0;
        for (int i = 0; i < sz; i++) {
            OffsettedItem one = items.get(i);
            try {
                int placedAt = one.place(this, outAt);

                if (placedAt < outAt) {
                    throw new RuntimeException("bogus place() result for " +
                            one);
                }

                outAt = placedAt + one.writeSize();
            } catch (RuntimeException ex) {
                throw ExceptionWithContext.withContext(ex,
                        "...while placing " + one);
            }
        }

        writeSize = outAt;
    }

    /** {@inheritDoc} */
    @Override
    protected void writeTo0(AnnotatedOutput out) {
        boolean annotates = out.annotates();
        boolean first = true;
        DexFile file = getFile();
        int at = 0;

        for (OffsettedItem one : items) {
            if (annotates) {
                if (first) {
                    first = false;
                } else {
                    out.annotate(0, "\n");
                }
            }

            int alignMask = one.getAlignment() - 1;
            int writeAt = (at + alignMask) & ~alignMask;

            if (at != writeAt) {
                out.writeZeroes(writeAt - at);
                at = writeAt;
            }

            one.writeTo(file, out);
            at += one.writeSize();
        }

        if (at != writeSize) {
            throw new RuntimeException("output size mismatch");
        }
    }
}
