package com.fp.dto.save;

import java.io.Serializable;
import java.math.BigDecimal;
import java.sql.Date;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import com.fp.dto.AbstractDataTransport;

/**
 * Dto de transporte utilizado en inserción, eliminación, actualización de datos en la base, adicionalmente permite
 * transportar información desde el front end, la misma que será utilizada en componentes de mantenimiento implementados
 * en el back end.e.
 * 
 * @author Jorge Vaca.
 * @version 2.1
 */
public class DtoSave implements Serializable {

    private static final long serialVersionUID = 2802444515156689856L;

    /** Nombre del bean a dar mantenimiento insert, update delete o financieros. */
    private String beanname;

    /** Lista de registros a eliminar de en la base de datos. */
    private final List<AbstractDataTransport> ldeleted = new ArrayList<AbstractDataTransport>();

    /** Lista de registros a insertar en la base de datos. */
    private List<AbstractDataTransport> linsert = new ArrayList<AbstractDataTransport>();

    /** Lista de objetos a modificar en la base de datos. */
    private List<HashMap<String, Object>> lupdated = new ArrayList<HashMap<String, Object>>();

    /** Posicion de grabado de los registros, por tabla */
    private Integer position;

    /** Datos adicionales utilizados en el mantenimiento */
    private HashMap<String, Object> mdata = new HashMap<String, Object>();

    /**
     * Atributo para identificar si enviamos un form
     */
    private boolean isForm;

    private boolean returnpk = false;

    /**
     * Crea una instancia de DtoSave.
     */
    public DtoSave() {
    }

    public void put(String key, Object value) {
        mdata.put(key, value);
    }

    public Object get(String key) {
        return mdata.get(key);
    }

    /**
     * Entrega un valor tipo String de un map.
     * 
     * @param key Key del map a obtener un valor.
     * @return String
     */
    public String getString(Object key) {
        // Si el valor en null retorna null.
        return (String) mdata.get(key);
    }

    /**
     * Entrega un valor tipo Date de un map.
     * 
     * @param key Key del map a obtener un valor.
     * @return Date
     */
    public Date getDate(Object key) {
        return (Date) mdata.get(key);
    }

    /**
     * Entrega un valor tipo Integer de un map.
     * 
     * @param key Key del map a obtener un valor.
     * @return Integer
     */
    public Integer getInteger(Object key) {
        try {
            return Integer.valueOf(mdata.get(key).toString());
        } catch (NumberFormatException e) {
            // Tiene que retornar null las clases internamete tienen validaciones.
            return null;
        } catch (NullPointerException e) {
            return null;
        }

    }

    /**
     * Entrega un valor tipo Long de un map.
     * 
     * @param key Key del map a obtener un valor.
     * @return Long
     */
    public Long getLong(Object key) {
        try {
            return Long.valueOf(mdata.get(key).toString());
        } catch (NumberFormatException e) {
            // Tiene que retornar null las clases internamete tienen validaciones.
            return null;
        } catch (NullPointerException e) {
            return null;
        }
    }

    /**
     * Entrega un valor tipo Long de un map.
     * 
     * @param key Key del map a obtener un valor.
     * @return Long
     */
    public BigDecimal getBigDecimal(Object key) {
        try {
            return BigDecimal.valueOf(Double.valueOf(mdata.get(key).toString()));
        } catch (NumberFormatException e) {
            // Tiene que retornar null las clases internamete tienen validaciones.
            return null;
        } catch (NullPointerException e) {
            return null;
        }
    }

    /**
     * Metodo que adiciona registros a crear en la base.
     * 
     * @param lnew Lista de datos a insertar en la base.
     * @throws Exception
     */
    public final void addNew(List<AbstractDataTransport> lnew) throws Exception {
        if (lnew.isEmpty()) {
            return;
        }
        linsert.addAll(lnew);
    }

    /**
     * Metodo que adiciona registros a actualizar en la base.
     * 
     * @param lupdate Lista de datos a modificar en la base.
     * @throws Exception
     */
    public final void addUpdated(List<HashMap<String, Object>> lupdate) throws Exception {
        if (lupdate.isEmpty()) {
            return;
        }
        lupdated.addAll(lupdate);
    }

    /**
     * Metodo que adiciona registros a eliminar de la base.
     * 
     * @param ldelete Lista de datos a eliminar en la base.
     * @throws Exception
     */
    public final void addDeleted(List<AbstractDataTransport> ldelete) throws Exception {
        if (ldelete.isEmpty()) {
            return;
        }
        ldeleted.addAll(ldelete);
    }

    /**
     * Metodo que verifica que el bean tenga acciones a realizar en la base.
     * 
     * @return boolean.
     * @throws Exception
     */
    public boolean pendingProcess() throws Exception {
        if (linsert.isEmpty() && lupdated.isEmpty() && ldeleted.isEmpty()) {
            return false;
        }
        return true;
    }

    /**
     * Entrega el valor de: beanname
     * 
     * @return String
     */
    public String getBeanname() {
        return beanname;
    }

    /**
     * Fija el valor de: beanname
     * 
     * @param Valor a fijar en el atributo.
     */
    public void setBeanname(String beanname) {
        this.beanname = beanname;
    }

    /**
     * Entrega el valor de: linsert
     * 
     * @return List<AbstractDataTransport>
     */
    public List<AbstractDataTransport> getLinsert() {
        return linsert;
    }

    /**
     * Fija el valor de: linsert
     * 
     * @param Valor a fijar en el atributo.
     */
    public void setLinsert(List<AbstractDataTransport> linsert) {
        this.linsert = linsert;
    }

    /**
     * Entrega el valor de: lupdated
     * 
     * @return List<HashMap<String,Object>>
     */
    public List<HashMap<String, Object>> getLupdated() {
        return lupdated;
    }

    /**
     * Fija el valor de: lupdated
     * 
     * @param Valor a fijar en el atributo.
     */
    public void setLupdated(List<HashMap<String, Object>> lupdated) {
        this.lupdated = lupdated;
    }

    /**
     * Entrega el valor de: position
     * 
     * @return Integer
     */
    public Integer getPosition() {
        return position;
    }

    /**
     * Fija el valor de: position
     * 
     * @param Valor a fijar en el atributo.
     */
    public void setPosition(Integer position) {
        this.position = position;
    }

    /**
     * Entrega el valor de: mdata
     * 
     * @return HashMap<String,Object>
     */
    public HashMap<String, Object> getMdata() {
        return mdata;
    }

    /**
     * Fija el valor de: mdata
     * 
     * @param Valor a fijar en el atributo.
     */
    public void setMdata(HashMap<String, Object> mdata) {
        this.mdata = mdata;
    }

    /**
     * Entrega el valor de: returnpk
     * 
     * @return boolean
     */
    public boolean isReturnpk() {
        return returnpk;
    }

    /**
     * Fija el valor de: returnpk
     * 
     * @param Valor a fijar en el atributo.
     */
    public void setReturnpk(boolean returnpk) {
        this.returnpk = returnpk;
    }

    /**
     * Entrega el valor de: ldeleted
     * 
     * @return List<AbstractDataTransport>
     */
    public List<Object> getLdeleted() {
        List<Object> l = new ArrayList<Object>();
        for (AbstractDataTransport obj : ldeleted) {
            l.add(obj);
        }
        return l;
    }

    /**
     * Entrega V/F si es formulario
     * 
     * @return isForm V/F
     */
    public boolean isIsForm() {
        return isForm;
    }

    /**
     * Fija V/F si es formulario
     * 
     * @param isForm V/F
     */
    public void setIsForm(boolean isForm) {
        this.isForm = isForm;
    }

}
