/*
 * 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 IntermediaryCode;

import ast.AbstractSyntaxTree;
import ast.Node;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Eugenio
 */
public class DataFrame {

    protected String name;
    protected LinkedHashMap<String, Node> values = new LinkedHashMap<>();//Map< String, String> copy = new TreeMap<>();
//    protected LinkedList<Node> values = new LinkedList<>();//Map< String, String> copy = new TreeMap<>();
//    protected HashMap<String, Integer> size = new LinkedHashMap<>();
//    protected HashMap<String, Integer> type = new LinkedHashMap<>();
//    protected HashMap<String, Integer> _offset_ = new LinkedHashMap<>();
    protected boolean initialized = false;
    protected static AbstractSyntaxTree ast;

    public static int TYPE_ARGUMENT = 0;
    public static int TYPE_VAR = 1;
    public static int TYPE_RETURN = 2;
    public static int TYPE_STACK = 3;

    public int offsetctrl = 0;
    protected DataFrame data;

    public DataFrame(String name, DataFrame data) {
        this.name = name;
        this.data = data;

    }

    public void setInicializar(boolean init) {
        initialized = init;
    }

    public DataFrame Add(String alias, Node var) {

        int size = Integer.parseInt(var.G("size"));

        for (int i = 0; i < size; i++) {
            values.put(alias + "." + i, var);
        }
        return this;
    }

    public LinkedHashMap<String, Node> values() {
        return values;
    }

    public boolean has(String id) {
        for (Map.Entry<String, Node> x : values.entrySet()) {
            if (x.getKey().equals(id)) {
                return true;
            }
        }
        return false;
    }

    public static void setAbstractSyntaxTree(AbstractSyntaxTree ast) {
        DataFrame.ast = ast;
    }

    public int Size() {
        int val = 0;
        for (Map.Entry<String, Node> v : values.entrySet()) {
            try {
                val += v.getValue().getInt("size");
            } catch (Exception ex) {
                Logger.getLogger(DataFrame.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        return val;
    }

    @Override
    public String toString() {
        StringBuilder s = new StringBuilder("Data Frame <" + name + ">:" + Size() + "\n");

        for (Map.Entry<String, Node> x : values.entrySet()) {
            s.append(x.getKey()).append(": ").append(x.getValue().G("name")).append("\n");
        }

        return s.toString();
    }

    /**
     * Formata oS haSh para a impreSSão no metodatao toString
     *
     * @param hash
     * @return
     */
    protected String hashToString(HashMap<String, Node> hash) {
        String r = "";
        for (Map.Entry<String, Node> entry : hash.entrySet()) {
            String name = entry.getKey();
            Node value = entry.getValue();
//            int type = this.type.G(name);
            r += "{" + name + ":" + value + "},";
        }
        return r;
    }

    public int Offset(String id) {
        if (id.contains("_G") && data != null) {
            return data.Offset(id);
        }
        int offset = 0;
        try {

            id = normalize(id);

            for (Map.Entry<String, Node> x : values.entrySet()) {
                if (!x.getKey().equals(id)) {
                    offset += x.getValue().getInt("size");
                    continue;
                }
                break;
            }
        } catch (Exception ex) {
            Logger.getLogger(DataFrame.class.getName()).log(Level.SEVERE, null, ex);
        }
        return offset;
    }

    protected String normalize(String id) {
        String shift = "0", or = id;

        if (id.contains("[")) {
            String[] parts = id.split("\\[");
            id = parts[0];
            shift = parts[1].replace("]", "");
        }

        if (!id.contains(".")) {
            id += "." + shift;
        }
//        System.out.println("Normalize:" + id + "::" + or);
        return id;
    }

    public DataFrame copy(DataFrame data) {
        for (Map.Entry<String, Node> x : data.values().entrySet()) {
            this.values.put(x.getKey(), x.getValue());
        }
        return this;
    }
}
