/*
 * 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.cf.code;

import com.android.dx.rop.code.RegisterSpec;
import com.android.dx.rop.type.Type;
import com.android.dx.rop.type.TypeBearer;
import com.android.dx.util.ExceptionWithContext;
import com.android.dx.util.Hex;
import com.android.dx.util.MutabilityControl;

import java.util.ArrayList;

/**
 * Representation of a set of local variable arrays, with Java semantics.
 * This peculiar case is to support in-method subroutines, which can
 * have different locals sets for each caller.
 *
 * <p><b>Note:</b> For the most part, the documentation for this class
 * ignores the distinction between {@link com.android.dx.rop.type.Type} and {@link
 * com.android.dx.rop.type.TypeBearer}.</p>
 */
public class LocalsArraySet extends LocalsArray {

    /**
     * The primary LocalsArray represents the locals as seen from
     * the subroutine itself, which is the merged representation of all the
     * individual locals states.
     */
    private final OneLocalsArray primary;

    /**
     * Indexed by label of caller block: the locals specific to each caller's
     * invocation of the subroutine.
     */
    private final ArrayList<LocalsArray> secondaries;

    /**
     * Constructs an instance. The locals array initially consists of
     * all-uninitialized values (represented as {@code null}s).
     *
     * @param maxLocals {@code >= 0;} the maximum number of locals this instance
     * can refer to
     */
    public LocalsArraySet(int maxLocals) {
        super(maxLocals != 0);
        primary = new OneLocalsArray(maxLocals);
        secondaries = new ArrayList();
    }

    /**
     * Constructs an instance with the specified primary and secondaries set.
     *
     * @param primary {@code non-null;} primary locals to use
     * @param secondaries {@code non-null;} secondaries set, indexed by subroutine
     * caller label.
     */
    public LocalsArraySet(OneLocalsArray primary,
            ArrayList<LocalsArray> secondaries) {
        super(primary.getMaxLocals() > 0);

        this.primary = primary;
        this.secondaries = secondaries;        
    }

    /**
     * Constructs an instance which is a copy of another.
     *
     * @param toCopy {@code non-null;} instance to copy.
     */
    private LocalsArraySet(LocalsArraySet toCopy) {
        super(toCopy.getMaxLocals() > 0);

        primary = toCopy.primary.copy();
        secondaries = new ArrayList(toCopy.secondaries.size());

        int sz = toCopy.secondaries.size();
        for (int i = 0; i < sz; i++) {
            LocalsArray la = toCopy.secondaries.get(i);

            if (la == null) {
                secondaries.add(null);
            } else {
                secondaries.add(la.copy());
            }
        }
    }


    /** @inheritDoc */
    @Override
    public void setImmutable() {
        primary.setImmutable();

        for (LocalsArray la : secondaries) {
            if (la != null) {
                la.setImmutable();
            }
        }
        super.setImmutable();
    }

    /** @inheritDoc */
    @Override
    public LocalsArray copy() {
        return new LocalsArraySet(this);
    }

    /** @inheritDoc */
    @Override
    public void annotate(ExceptionWithContext ex) {
        ex.addContext("(locals array set; primary)");
        primary.annotate(ex);

        int sz = secondaries.size();
        for (int label = 0; label < sz; label++) {
            LocalsArray la = secondaries.get(label);

            if (la != null) {
                ex.addContext("(locals array set: primary for caller "
                        + Hex.u2(label) + ')');

                la.getPrimary().annotate(ex);
            }
        }
    }

    /** {@inheritDoc*/
    public String toHuman() {
        StringBuilder sb = new StringBuilder();

        sb.append("(locals array set; primary)\n");

        sb.append(getPrimary().toHuman());
        sb.append('\n');

        int sz = secondaries.size();
        for (int label = 0; label < sz; label++) {
            LocalsArray la = secondaries.get(label);

            if (la != null) {
                sb.append("(locals array set: primary for caller "
                        + Hex.u2(label) + ")\n");

                sb.append(la.getPrimary().toHuman());
                sb.append('\n');
            }
        }

        return sb.toString();
    }

    /** @inheritDoc */
    @Override
    public void makeInitialized(Type type) {
        int len = primary.getMaxLocals();

        if (len == 0) {
            // We have to check for this before checking for immutability.
            return;
        }

        throwIfImmutable();

        primary.makeInitialized(type);

        for (LocalsArray la : secondaries) {
            if (la != null) {
                la.makeInitialized(type);
            }
        }
    }

    /** @inheritDoc */
    @Override
    public int getMaxLocals() {
        return primary.getMaxLocals();
    }

    /** @inheritDoc */
    @Override
    public void set(int idx, TypeBearer type) {
        throwIfImmutable();

        primary.set(idx, type);

        for (LocalsArray la : secondaries) {
            if (la != null) {
                la.set(idx, type);
            }
        }
    }

    /** @inheritDoc */
    @Override
    public void set(RegisterSpec spec) {
        set(spec.getReg(), spec);
    }

    /** @inheritDoc */
    @Override
    public void invalidate(int idx) {
        throwIfImmutable();

        primary.invalidate(idx);

        for (LocalsArray la : secondaries) {
            if (la != null) {
                la.invalidate(idx);
            }
        }
    }

    /** @inheritDoc */
    @Override
    public TypeBearer getOrNull(int idx) {
        return primary.getOrNull(idx);
    }

    /** @inheritDoc */
    @Override
    public TypeBearer get(int idx) {
        return primary.get(idx);
    }

    /** @inheritDoc */
    @Override
    public TypeBearer getCategory1(int idx) {
        return primary.getCategory1(idx);
    }

    /** @inheritDoc */
    @Override
    public TypeBearer getCategory2(int idx) {
        return primary.getCategory2(idx);
    }

    /**
     * Merges this set with another {@code LocalsArraySet} instance.
     *
     * @param other {@code non-null;} to merge
     * @return {@code non-null;} this instance if merge was a no-op, or
     * new merged instance.
     */
    private LocalsArraySet mergeWithSet(LocalsArraySet other) {
        OneLocalsArray newPrimary;
        ArrayList<LocalsArray> newSecondaries;
        boolean secondariesChanged = false;

        newPrimary = primary.merge(other.getPrimary());

        int sz1 = secondaries.size();
        int sz2 = other.secondaries.size();
        int sz = Math.max(sz1, sz2);
        newSecondaries = new ArrayList(sz);

        for (int i = 0; i < sz; i++) {
            LocalsArray la1 = (i < sz1 ? secondaries.get(i) : null);
            LocalsArray la2 = (i < sz2 ? other.secondaries.get(i) : null);
            LocalsArray resultla = null;

            if (la1 == la2) {
                resultla = la1;
            } else if (la1 == null) {
                resultla = la2;
            } else if (la2 == null) {
                resultla = la1;
            } else {
                try {
                    resultla = la1.merge(la2);
                } catch (SimException ex) {
                    ex.addContext(
                            "Merging locals set for caller block " + Hex.u2(i));
                }
            }

            secondariesChanged = secondariesChanged || (la1 != resultla);

            newSecondaries.add(resultla);
        }

        if ((primary == newPrimary) && ! secondariesChanged ) {
            return this;
        }

        return new LocalsArraySet(newPrimary, newSecondaries);
    }

    /**
     * Merges this set with a {@code OneLocalsArray} instance.
     *
     * @param other {@code non-null;} to merge
     * @return {@code non-null;} this instance if merge was a no-op, or
     * new merged instance.
     */
    private LocalsArraySet mergeWithOne(OneLocalsArray other) {
        OneLocalsArray newPrimary;
        ArrayList<LocalsArray> newSecondaries;
        boolean secondariesChanged = false;

        newPrimary = primary.merge(other.getPrimary());
        newSecondaries = new ArrayList(secondaries.size());

        int sz = secondaries.size();
        for (int i = 0; i < sz; i++) {
            LocalsArray la = secondaries.get(i);
            LocalsArray resultla = null;

            if (la != null) {
                try {
                    resultla = la.merge(other);
                } catch (SimException ex) {
                    ex.addContext("Merging one locals against caller block "
                                    + Hex.u2(i));
                }
            }

            secondariesChanged = secondariesChanged || (la != resultla);

            newSecondaries.add(resultla);
        }

        if ((primary == newPrimary) && ! secondariesChanged ) {
            return this;
        }

        return new LocalsArraySet(newPrimary, newSecondaries);
    }

    /** @inheritDoc */
    @Override
    public LocalsArraySet merge(LocalsArray other) {
        LocalsArraySet result;

        try {
            if (other instanceof LocalsArraySet) {
                result = mergeWithSet((LocalsArraySet) other);
            } else {
                result = mergeWithOne((OneLocalsArray) other);
            }
        } catch (SimException ex) {
            ex.addContext("underlay locals:");
            annotate(ex);
            ex.addContext("overlay locals:");
            other.annotate(ex);
            throw ex;
        }

        result.setImmutable();
        return result;
    }

    /**
     * Gets the {@code LocalsArray} instance for a specified subroutine
     * caller label, or null if label has no locals associated with it.
     *
     * @param label {@code >= 0;} subroutine caller label
     * @return {@code null-ok;} locals if available.
     */
    private LocalsArray getSecondaryForLabel(int label) {
        if (label >= secondaries.size()) {
            return null;
        }

        return secondaries.get(label);
    }

    /** {@inheritDoc} */
    @Override
    public LocalsArraySet mergeWithSubroutineCaller
            (LocalsArray other, int predLabel) {

        LocalsArray mine = getSecondaryForLabel(predLabel);
        LocalsArray newSecondary;
        OneLocalsArray newPrimary;

        newPrimary = primary.merge(other.getPrimary());

        if (mine == other) {
            newSecondary = mine;
        } else if (mine == null) {
            newSecondary = other;
        } else {
            newSecondary = mine.merge(other);
        }

        if ((newSecondary == mine) && (newPrimary == primary)) {
            return this;
        } else {
            /*
             * We're going to re-build a primary as a merge of all the
             * secondaries.
             */
            newPrimary = null;

            int szSecondaries = secondaries.size();
            int sz = Math.max(predLabel + 1, szSecondaries);
            ArrayList<LocalsArray> newSecondaries = new ArrayList(sz);
            for (int i = 0; i < sz; i++) {
                LocalsArray la = null;

                if (i == predLabel) {
                    /*
                     * This LocalsArray always replaces any existing one,
                     * since this is the result of a refined iteration.
                     */
                    la = newSecondary;
                } else if (i < szSecondaries) {
                    la = secondaries.get(i);
                }

                if (la != null) {
                    if (newPrimary == null) {
                        newPrimary = la.getPrimary();
                    } else {
                        newPrimary = newPrimary.merge(la.getPrimary());
                    }
                }

                newSecondaries.add(la);
            }

            LocalsArraySet result
                    = new LocalsArraySet(newPrimary, newSecondaries);
            result.setImmutable();
            return result;
        }
    }

    /**
     * Returns a LocalsArray instance representing the locals state that should
     * be used when returning to a subroutine caller.
     *
     * @param subLabel {@code >= 0;} A calling label of a subroutine
     * @return {@code null-ok;} an instance for this subroutine, or null if subroutine
     * is not in this set.
     */
    public LocalsArray subArrayForLabel(int subLabel) {
        LocalsArray result = getSecondaryForLabel(subLabel);
        return result;
    }

    /**{@inheritDoc}*/
    @Override
    protected OneLocalsArray getPrimary() {
        return primary;
    }
}
