package com.fp.dto;

import java.beans.PropertyChangeEvent;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.beanutils.BeanMap;

import com.fp.common.helper.BeanManager;
import com.fp.dto.hb.HibernateId;

public abstract class AbstractData extends HashMap<String, Object> implements Serializable {

    /** Version de la clase. */
    private static final long serialVersionUID = 1L;

    // protected PropertyChangeSupport pcs = new PropertyChangeSupport(this);
    private final Map<String, Object> modifiedData = new HashMap<String, Object>();

    // private boolean modified = false;

    public Map<String, Object> modifiedData() {
        return modifiedData;
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    private void verifyField(String pField, Object pOld, Object pNew) {
        if (pOld == pNew) {
            return;
        }
        if (pOld == null && pNew != null) {
            this.putFieldModified(pField, "null");
            return;
        }
        if (pOld != null && pNew == null) {
            this.putFieldModified(pField, pOld);
            return;
        }
        if (pOld.getClass().getName().compareTo(pNew.getClass().getName()) != 0) {
            this.putFieldModified(pField, pOld);
            return;
        }
        if (pOld instanceof Comparable) {
            if (((Comparable) pOld).compareTo(pNew) != 0) {
                this.putFieldModified(pField, pOld);
                return;
            }
        }
        this.putFieldModified(pField, pOld);
    }

    private void putFieldModified(String pField, Object pData) {
        if (!this.modifiedData.containsKey(pField)) {
            // modified = true;
            modifiedData.put(pField, pData);
        }
    }

    
    /**
	 * Entrega el valor de: modifiedData
	 * @return Map<String,Object>
	 */
	public Map<String, Object> getModifiedData() {
		return modifiedData;
	}

	public void propertyChange(PropertyChangeEvent evt) {
        this.verifyField(evt.getPropertyName(), evt.getOldValue(), evt.getNewValue());
    }

    /*
     * public PropertyChangeSupport getPcs() { return pcs; }
     */
    public void clean() {
        // this.modified=false;
        this.modifiedData.clear();
    }

    public String getTransportBeanClass() {
        return this.getClass().getCanonicalName();
    }

    public void addAddtionalInfo(String pName, Object pValue) {
        super.put(pName, pValue);
    }

    /*
     * (non-Javadoc)
     * 
     * @see java.util.HashMap#entrySet()
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    @Override
    public Set<java.util.Map.Entry<String, Object>> entrySet() {
        Field[] fs1 = this.getClass().getDeclaredFields();
        List<Field> fs = new ArrayList<Field>();
        for (Field f : fs1) {
            fs.add(f);
        }
        try {
            Class csuper = this.getClass().getSuperclass();
            do {
                if (csuper != null) {
                    Field[] fs2 = csuper.getDeclaredFields();
                    for (Field f : fs2) {
                        fs.add(f);
                    }
                }
                csuper = csuper.getSuperclass();
            } while (csuper != null);
        } catch (Exception e) {
        }
        for (Field field : fs) {
            try {
                String name = field.getName();
                if (name.compareTo("serialVersionUID") == 0) {
                    continue;
                }
                Object val = null;
                try {
                    val = BeanManager.getBeanAttributeValue(this, name);
                } catch (Exception e1) {
                    continue;
                }
                if (val instanceof HibernateId) {
                    BeanMap bm = new BeanMap(val);
                    Set<java.util.Map.Entry<String, Object>> ent = bm.entrySet();
                    for (java.util.Map.Entry<String, Object> e : ent) {
                        String key = e.getKey();
                        if (key.compareTo("class") == 0 || key.compareTo("transportBeanClass") == 0 || key.compareTo("empty") == 0) {
                            // key = "transportBeanClass"; para que no envie el transportbeanclass
                            continue;
                        }
                        super.put(name + "_" + key, e.getValue());
                    }
                    continue;
                }
                super.put(name, val);
            } catch (Exception e) {
                continue;
            }
        }
        // super.put("transportBeanClass", this.getTransportBeanClass());
        return super.entrySet();
    }

    public Set<java.util.Map.Entry<String, Object>> entrySetDefault() {
        return super.entrySet();
    }
}
