/*
 * @author Ranides Atterwim <ranides@gmail.com>
 * @copyright Ranides Atterwim
 * @license WTFPL
 * @url http://ranides.net/projects/assira
 */
package net.ranides.assira.asm;

import java.util.Map;
import net.ranides.asm.Label;

/**
 * Klasa abstrakcyjna służąca do zarządzania etykietami ASM. Klasa
 * ma pilnować, aby każda etykieta była deklarowana w kodzie tylko raz oraz żeby
 * każde odwołanie do tej samej instancji {@link Label} było konwertowane do tego
 * samego tekstu.
 * @author ranides
 */
public abstract class AsmLabeler {

    /**
     * Zapamiętuje podaną etykietę wykrytą przez ASM podczas analizy. Jeśli
     * etykiety wcześniej nie było, to rezerwuje dla niej nazwę zmiennej, przez
     * którą będzie reprezentowana w generowanym kodzie.
     * @param value
     * @return this
     */
    public abstract AsmLabeler declare(Label value);

    /**
     * Zapamiętuje podane etykiety wykryte przez ASM podczas analizy.
     * Dla każdej etykiety rezerwuje nazwę zmiennej, która będzie ją reprezentować
     * w generowanym kodzie - o ile wcześniej etykieta nie została już zadeklarowana.
     * @param values
     * @return this
     */
    public final AsmLabeler declare(Label[] values) {
        for(Label value : values) {
            declare(value);
        }
        return this;
    }

    /**
     * Przegląda pierwsze {@code size} elementów z podanej tablicy, jeśli element
     * jest etykietą (instancją {@link Label}), to ją deklaruje.
     * @param size
     * @param values
     * @return
     */
    public final AsmLabeler declare(final int size, final Object[] values) {
        for(int i = 0; i < size; ++i) {
            if (values[i] instanceof Label) {
                declare( (Label)values[i] );
            }
        }
        return this;
    }

    /**
     * Zwraca mapę tylko do odczytu, która zawiera wszystkie zadeklarowane etykiety.
     * @return
     */
    public abstract Map<Label, String> map();

}
