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

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

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

    protected HashMap<String, String> attr;
    protected HashMap<String, ArrayList<String>> lists;

    public Instruction parent;
    public Instruction next;
    public Instruction prev;

    public HashMap<String, ArrayList<String>> GetLists() {
        return lists;
    }

    public RegistroBase() {
        lists = new LinkedHashMap<>();
        attr = new LinkedHashMap<>();
    }

    public void addList(String nome, ArrayList<String> lista) {
        lists.put(nome, lista);
    }

    public boolean existeLista(String nome) {
        return lists.containsKey(nome);
    }

    public void addInList(String nome, String value) {
        getList(nome).add(value);
    }

    public ArrayList<String> getList(String nome) {
        if (!existeLista(nome)) {
            lists.put(nome, new ArrayList<String>());
        }
        return lists.get(nome);
    }

    public void setParent(Instruction n) {
        parent = n;
    }

    public String Get(String attrib) {
        return attr.containsKey(attrib) ? attr.get(attrib) : "";
    }

    public String Get(String attrib, String orValue) {
        String val = Get(attrib);
        return (val.equals("")) ? orValue : val;
    }

    public String format(String f) {
        String value = "";
        for (Map.Entry<String, String> entry : this.getProps().entrySet()) {
            value = entry.getValue() != null ? entry.getValue() : "NULL";
            f = f.replaceAll("\\{" + entry.getKey() + "\\}", value);
        }
        return f;
    }

    public RegistroBase Set(String attrib, String value) {
        attr.put(attrib, value);
        return this;
    }

    public RegistroBase Replace(String attrib, String regex, String value) {
//        attr.put(attrib, value);
        if (Has(attrib)) {
            RegistroBase.this.Set(attrib, Get(attrib).replaceAll(regex, value));
        }
        return this;
    }

    public RegistroBase R(String attributes) {
        String[] attrs = attributes.split(",");
        for (String a1 : attrs) {
            if (this.attr.containsKey(a1)) {
                this.attr.remove(a1);
            }
        }
        return this;
    }

    public boolean testAndSet(String atributo, String cmp, String valor) {
        if (eq(atributo, cmp)) {
            RegistroBase.this.Set(atributo, valor);
            return true;
        }
        return false;
    }

    public boolean contem(String atributo, String part) {
        if (!Has(atributo)) {
            return false;
        }
        return Get(atributo).contains(part);
    }

    @Override
    public String toString() {
        String reg = "";
        for (Map.Entry<String, String> entry : attr.entrySet()) {
            String string = entry.getKey();
            String string1 = entry.getValue();
            reg += "\t" + string + ":" + string1 + ",\n";
        }
        return ":\n" + reg;

    }

    public void sum(String atributo, int i) {
        if (!Has(atributo)) {
            Set(atributo, i);
        } else {
            try {
                int nu = GetInt(atributo);
                Set(atributo, nu + i);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public RegistroBase Set(String attrib, Long valor) {
        RegistroBase.this.Set(attrib, "" + valor);
        return this;
    }

    public RegistroBase Set(String attrib, int valor) {
        RegistroBase.this.Set(attrib, "" + valor);
        return this;
    }

    public RegistroBase Set(String attrib, Boolean valor) {
        RegistroBase.this.Set(attrib, "" + valor);
        return this;
    }

    public String getText() {
        return Get("value");
    }

    public String getRegistroClass() {
        return Get("class");
    }

    public String getValorOuVazio(String string) {
        return (attr.containsKey(string)) ? attr.get(string) : "";
    }

    public boolean Has(String at) {
        return attr.containsKey(at);
    }

    public HashMap<String, String> getProps() {
        return attr;
    }

    public void del(String atrib) {
        attr.remove(atrib);
    }

    public int GetInt(String atributo) throws Exception {
        String l = "";
        try {
            l = Get(atributo);
            return Integer.parseInt(l);
        } catch (Exception e) {
            throw new Exception("[ID:" + Get("id") + "]O atributo {" + atributo + ":'" + l + "'} não é inteiro.");
        }
    }

    public long getLong(String atributo) throws Exception {
        String l = "";
        try {
            l = Get(atributo);
            return Long.parseLong(l);
        } catch (Exception e) {
            throw new Exception("[ID:" + Get("id") + "]O atributo {" + atributo + ":'" + l + "'} não é long.");
        }
    }

    public boolean eq(String attrib, String value) {
        if (!attr.containsKey(attrib)) {
            return false;
        }
        return attr.get(attrib).equals(value);
    }

    public boolean in(String atributo, ArrayList<String> sources) {
        if (!attr.containsKey(atributo)) {
            return false;
        }

        boolean in = false;

        for (String valor : sources) {
            if (attr.get(atributo).equals(valor)) {
                in = true;
                break;
            }
        }

        return in;

    }

    public boolean in(String atributo, String[] valores) {
        return in(atributo, new ArrayList<>(Arrays.asList(valores)));
    }

    public boolean diferente(String atributo, String valor) {
        return !attr.get(atributo).equals(valor);
    }

    /**
     * Verifica Se um dado atributo é numerico.
     *
     * @param atributo
     * @return
     */
    public boolean isNumber(String atributo) {
        try {
            Integer.parseInt(Get(atributo).replaceAll("\\s*", ""));
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * Copia o dado do regiStro r com atributio Fonte para regiStro atual
     * mantendo o nome do atributo
     *
     * @param atribs Fonte
     * @param r
     */
    public RegistroBase copy(String attribs, RegistroBase r) {
        if (attribs.equals("")) {
            String key;
            for (Map.Entry<String, String> entry : r.getProps().entrySet()) {
                key = entry.getKey();
                Set(key, r.Get(key));
            }
        } else {
            for (String attr : attribs.split(",")) {
                Set(attr, r.Get(attr));
            }
        }

        return this;
    }

    /**
     * Copia o dado do regiStro r com atributio Fonte para o atributo deStino no
     * regiStro atual
     *
     * @param atribs Fonte
     * @param atribd DeStino
     * @param r
     */
    public RegistroBase copy(String atribs, String atribd, RegistroBase r) {
        RegistroBase.this.Set(atribd, r.Get(atribs));
        return this;
    }

    /**
     * Copy retorna um novo RegistroBase contendo todos os atributos do registro
     * fonte.
     *
     * @return
     */
    public RegistroBase copy() {
        RegistroBase rb = new RegistroBase();
        for (Map.Entry<String, String> entry : attr.entrySet()) {
            rb.Set(entry.getKey(), entry.getValue());
        }
        return rb;
    }

}
