/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package templates;

import API.Api;
import API.Utils;
import common.RegistroBase;
import exception.CompileException;
import java.util.ArrayList;
import java.util.HashMap;

/**
 *
 * @author EUGENIO CARVALHO
 */
public class Functions {

    protected static HashMap<String, FunctionInterface> functions = new HashMap<String, FunctionInterface>() {
        {

            // Funcao que inseri tabulações no texto.
            // O primeiro parametro indica a quantidade de tabulações
//                System.out.println("Tabulation:'" + Utils.Repeat("\t", args.get(0)) + "'");
            put("T", (FunctionInterface) (ctx, args) -> Utils.Repeat("\t", args.get(0)));

            // Função formata label
            put("L", (FunctionInterface) (ctx, args) -> " <" + args.get(0) + ">");

            // Converte um numero para binario e adiciona pad informado no segundo parametro
            put("BIN", (ctx, args) -> Functions.BIN(args));

            // 
            put("HEX", (FunctionInterface) (ctx, args) -> {
                String value = args.get(0);
                if (!value.equals("")) {
                    if (!Utils.IsNumber(value)) {
                        value = ctx.Get(value);
                    }
                    value = Utils.FormatNum(value, "hex");
                    return Utils.Pad(value, args.get(2), "", Integer.parseInt(args.get(1)));
                }
                return "";
            });

            put("DEC", (FunctionInterface) (ctx, args) -> {
                String value = args.get(0);
                if (!value.equals("")) {
                    return Utils.Pad(value, args.get(2), "", Integer.parseInt(args.get(1)));
                }
                return "";
            });

            put("PAD", (FunctionInterface) (ctx, args) -> {
                String value = args.get(0);
                if (args.size() > 1) {
//                    System.out.println("PAD:" + args);
                    value = Utils.Pad(value, args.get(2), "", Integer.parseInt(args.get(1)));
                }
                return value;
            });

        }

    };

    public static void Add(String id, FunctionInterface f) {
        functions.put(id, f);
    }

    public static FunctionInterface Get(String id) throws Exception {

        if (!functions.containsKey(id)) {
            throw new Exception(String.format("Função de template %s não definida.", id));
        }

        return functions.get(id);
    }

    public static String Call(String id, RegistroBase ctx, ArrayList<String> args) throws Exception {
        try {
            return Get(id).Call(ctx, args);
        } catch (Exception e) {
            throw new CompileException("Erro na chamada '%s': %s", id, e.getMessage());
        }
    }

    // Utils functions
    public static String BIN(ArrayList<String> arguments) {
        return BIN(arguments.get(0), arguments.get(1));
    }

    public static String BIN(String val, String pad) {
        return BIN(val, Integer.parseInt(pad));
    }

    public static String BIN(String val, int pad) {
        return Api.num2bin(val, pad);
    }
}
