/*
 * 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.rop.cst.Constant;
import com.android.dx.rop.cst.CstType;
import com.android.dx.rop.type.Type;
import com.android.dx.rop.type.TypeList;
import com.android.dx.util.AnnotatedOutput;
import com.android.dx.util.Hex;
import java.util.ArrayList;
import java.util.Collection;
import java.util.TreeMap;

/**
 * Class definitions list section of a {@code .dex} file.
 */
public final class ClassDefsSection extends UniformItemSection {
    /**
     * {@code non-null;} map from type constants for classes to {@link
     * ClassDefItem} instances that define those classes
     */
    private final TreeMap<Type, ClassDefItem> classDefs;

    /** {@code null-ok;} ordered list of classes; set in {@link #orderItems} */
    private ArrayList<ClassDefItem> orderedDefs;

    /**
     * Constructs an instance. The file offset is initially unknown.
     *
     * @param file {@code non-null;} file that this instance is part of
     */
    public ClassDefsSection(DexFile file) {
        super("class_defs", file, 4);

        classDefs = new TreeMap<Type, ClassDefItem>();
        orderedDefs = null;
    }

    /** {@inheritDoc} */
    @Override
    public Collection<? extends Item> items() {
        if (orderedDefs != null) {
            return orderedDefs;
        }

        return classDefs.values();
    }

    /** {@inheritDoc} */
    @Override
    public IndexedItem get(Constant cst) {
        if (cst == null) {
            throw new NullPointerException("cst == null");
        }

        throwIfNotPrepared();

        Type type = ((CstType) cst).getClassType();
        IndexedItem result = classDefs.get(type);

        if (result == null) {
            throw new IllegalArgumentException("not found");
        }

        return result;
    }

    /**
     * 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();

        int sz = classDefs.size();
        int offset = (sz == 0) ? 0 : getFileOffset();

        if (out.annotates()) {
            out.annotate(4, "class_defs_size: " + Hex.u4(sz));
            out.annotate(4, "class_defs_off:  " + Hex.u4(offset));
        }

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

    /**
     * Adds an element to this instance. It is illegal to attempt to add more
     * than one class with the same name.
     *
     * @param clazz {@code non-null;} the class def to add
     */
    public void add(ClassDefItem clazz) {
        Type type;

        try {
            type = clazz.getThisClass().getClassType();
        } catch (NullPointerException ex) {
            // Elucidate the exception.
            throw new NullPointerException("clazz == null");
        }

        throwIfPrepared();

        if (classDefs.get(type) != null) {
            throw new IllegalArgumentException("already added: " + type);
        }

        classDefs.put(type, clazz);
    }

    /** {@inheritDoc} */
    @Override
    protected void orderItems() {
        int sz = classDefs.size();
        int idx = 0;

        orderedDefs = new ArrayList<ClassDefItem>(sz);

        /*
         * Iterate over all the classes, recursively assigning an
         * index to each, implicitly skipping the ones that have
         * already been assigned by the time this (top-level)
         * iteration reaches them.
         */
        for (Type type : classDefs.keySet()) {
            idx = orderItems0(type, idx, sz - idx);
        }
    }

    /**
     * Helper for {@link #orderItems}, which recursively assigns indices
     * to classes.
     *
     * @param type {@code null-ok;} type ref to assign, if any
     * @param idx {@code >= 0;} the next index to assign
     * @param maxDepth maximum recursion depth; if negative, this will
     * throw an exception indicating class definition circularity
     * @return {@code >= 0;} the next index to assign
     */
    private int orderItems0(Type type, int idx, int maxDepth) {
        ClassDefItem c = classDefs.get(type);

        if ((c == null) || (c.hasIndex())) {
            return idx;
        }

        if (maxDepth < 0) {
            throw new RuntimeException("class circularity with " + type);
        }

        maxDepth--;

        CstType superclassCst = c.getSuperclass();
        if (superclassCst != null) {
            Type superclass = superclassCst.getClassType();
            idx = orderItems0(superclass, idx, maxDepth);
        }

        TypeList interfaces = c.getInterfaces();
        int sz = interfaces.size();
        for (int i = 0; i < sz; i++) {
            idx = orderItems0(interfaces.getType(i), idx, maxDepth);
        }

        c.setIndex(idx);
        orderedDefs.add(c);
        return idx + 1;
    }
}
