package com.fp.frontend.controller.armas.parametros;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;

import org.primefaces.event.SelectEvent;

import com.fp.dto.Request;
import com.fp.dto.Response;
import com.fp.dto.query.DtoQuery;
import com.fp.dto.query.SubQuery;
import com.fp.dto.save.DtoSave;
import com.fp.frontend.controller.AbstractController;
import com.fp.frontend.controller.pcustomer.lov.PersonLovController;
import com.fp.frontend.controller.pgeneral.gene.CantonController;
import com.fp.frontend.controller.pgeneral.gene.CatalogDetailController;
import com.fp.frontend.controller.pgeneral.gene.CityController;
import com.fp.frontend.controller.pgeneral.gene.ParroquiaController;
import com.fp.frontend.controller.pgeneral.gene.ProvinceController;
import com.fp.frontend.helper.MessageHelper;
import com.fp.frontend.utility.MsgControlArmas;
import com.fp.persistence.parmas.param.TarmSitioAlmacenamiento;
import com.fp.persistence.pcustomer.gene.TcustPersonDetail;
import com.fp.persistence.pgeneral.gene.TgeneCanton;
import com.fp.persistence.pgeneral.gene.TgeneCatalogDetail;
import com.fp.persistence.pgeneral.gene.TgeneCity;
import com.fp.persistence.pgeneral.gene.TgeneParroquia;
import com.fp.persistence.pgeneral.gene.TgeneProvince;

/**
 * Clase controladora del bean TarmSitioAlmacenamiento.
 *
 * @author C.P.
 * @version 2.1
 */
@SuppressWarnings("serial")
@ManagedBean
@ViewScoped
public class SitioAlmacenamientoController extends AbstractController<TarmSitioAlmacenamiento> {

    /**
     * latitud de la dirección en el google map
     */
    private String latitud;
    /**
     * longitud de la dirección en el google map
     */
    private String longitud;
    /**
     * direccion en la que se va ha visualizar el map
     */
    private String direccionGoogleMap;

    public SitioAlmacenamientoController() throws Exception {
        super(TarmSitioAlmacenamiento.class);
    }

    /**
     * Atributo para la lista de objetos TgeneProvince
     */
    private List<TgeneProvince> lprovinces;

    /**
     * Atributo para la lista de objetos TgeneProvince
     */
    private List<TgeneCanton> lcantones;

    /**
     * Atributo para la lista de objetos TgeneProvince
     */
    private List<TgeneParroquia> lparroquias;

    /**
     * Atributo para la lista de objetos TgeneProvince
     */
    private List<TgeneCity> lcities;

    /**
     * Atributo para la lista de objetos TgeneCatalogDetail
     */
    private List<TgeneCatalogDetail> tipoComercio;

    private Boolean btnEditar = Boolean.FALSE;

    /**
     * tipoMapa permite visualizar la posicion del mapa por direccion o por
     * coordenadas
     */
    private String tipoMapa;

    private String latitudG;
    private String latitudM;
    private String latitudS;
    private String longuitudG;
    private String longuitudM;
    private String longuitudS;

    private String latitudGMS;
    private String longitudGMS;

    @PostConstruct
    private void postconstruct() {
        setDireccionGoogleMap("Ecuador");
        this.init();
        // Inicializa autoconsulta
        super.startQuery();

    }

    /**
     * Incializa el controlador, cuando se esta utilizando una pagina que utliza
     * el controlador.
     */
    private void init() {
        try {
            this.recperpage = 15; // Cambiar al # reg a mirar.
            this.lrecord = new ArrayList<>();
            this.beanalias = "CATALOGDETAIL";
            lprovinces = ProvinceController.find("EC");
            tipoComercio = CatalogDetailController.find("TIPOCOMERCIO");
        } catch (Exception e) {
            MessageHelper.setMessageError(e);
        }
    }

    /**
     * Crea una instancia de TgeneTransactionProcess y marca el registro como
     * nuevo.
     *
     * @throws Exception
     */
    @Override
    public void create() throws Exception {
        super.create();
        record.setCountrycode("EC");
        record.setTipocomerciocodigo("TIPOCOMERCIO");
        record.setEstado("ACT");
        btnEditar = Boolean.FALSE;

        if (this.getMfilters().get("pk.personcode") != null) {
            record.setPersoncode(Integer.parseInt(this.getMfilters().get("pk.personcode").toString()));
            record.getModifiedData().put("nombre", this.getMfilelds().get("nombre"));
            record.getModifiedData().put("numeroDocumento", this.getMfilelds().get("numeroDocumento"));
        }
        if (this.getMfilters().get("tipocomercio") != null) {
            record.setTipocomercio(this.getMfilters().get("tipocomercio").toString());
        }
    }

    @Override
    public void update() throws Exception {
//-------------------validar SELECCION TIPO UBICACION		
        if (tipoMapa == null || "".equals(tipoMapa)) {
            MessageHelper.setMessageError(MsgControlArmas.getProperty("mg_error_seleccioneeltipoMapa"));
            return;
        }
//-------------------validar LATITUD Y LONGITUD		
        if (record.getLatitud() == null || record.getLongitud() == null) {
            MessageHelper.setMessageError(MsgControlArmas.getProperty("mg_error_seleccioneeltipodedocumentooingreselongitudlatitud"));
            return;
        }

        if (record.getPersoncode() == null) {
            MessageHelper.setMessageError(MsgControlArmas.getProperty("msg_error_numerodocumento"));
            return;
        }
        catalogos(tipoComercio, record.getTipocomercio(), "tipocomercio");
        super.update();
        btnEditar = Boolean.TRUE;
    }

    public void edit() {
        executeProvince();
        executeCanton();
        btnEditar = Boolean.TRUE;
    }

    @SuppressWarnings("unchecked")
    @Override
    protected void querydatabase() {
        try {
            this.addFilter("estado", "ACT");
            DtoQuery dto = super.getDtoQuery(true);
            dto.setOrderby("t.bodega");
            SubQuery snombre = new SubQuery("TcustPersonDetail", "name", "nombre", "i.pk.personcode = t.personcode and  i.pk.dateto=(select max(dt.pk.dateto) from TcustPersonDetail dt where dt.pk.personcode=t.personcode)");
            SubQuery snumerodocumento = new SubQuery("TcustPersonDetail", "identification", "numeroDocumento", "i.pk.personcode = t.personcode and  i.pk.dateto=(select max(dt.pk.dateto) from TcustPersonDetail dt where dt.pk.personcode=t.personcode)");
            SubQuery tipoComercio = new SubQuery("TgeneCatalogDetail", "description", "tipocomercio", "i.pk.catalog = t.tipocomercio and  i.pk.catalogcode=t.tipocomerciocodigo");

            dto.addSubQuery(snombre);
            dto.addSubQuery(snumerodocumento);
            dto.addSubQuery(tipoComercio);

            HashMap<String, DtoQuery> mtables = new HashMap<String, DtoQuery>();
            mtables.put(this.beanalias, dto); // permite adicionar mas de una tabla.

            Request request = this.callerhelper.getRequest();
            request.setQueryTables(mtables);

            Response resp = this.callerhelper.executeQuery(request);

            if (resp.getResponseCode().compareTo(Response.RESPONSE_OK) != 0) {
                this.lrecord = new ArrayList<TarmSitioAlmacenamiento>();
                MessageHelper.setMessageError(resp);
            } else {
                this.lrecord = (List<TarmSitioAlmacenamiento>) resp.get(this.beanalias);
                super.postQuery(this.lrecord);
            }

        } catch (Throwable e) {
            MessageHelper.setMessageError(e);
        }
    }

    @Override
    public void save() {
        try {
            DtoSave dtosave = super.getDtoSave();
            dtosave.setReturnpk(true); // Para que el core devuelva el pk de los registros nuevos.
            HashMap<String, DtoSave> msave = new HashMap<String, DtoSave>();

            Request request = this.callerhelper.getRequest();
            msave.put(this.beanalias, dtosave); // adicionar metadata de mantenimiento para cada tabla.

            request.setSaveTables(msave);
            Response resp = this.callerhelper.executeSave(request);
            if (resp.getResponseCode().compareTo(Response.RESPONSE_OK) == 0) {
                this.postCommit(resp);
                MessageHelper.setMessageInfo(resp);
            } else {
                MessageHelper.setMessageError(resp);
            }
        } catch (Throwable e) {
            MessageHelper.setMessageError(e);
        }
    }

    public void remove() {
        if (this.record != null) {
            this.record.setEstado("INA");
            try {
                removefromlista(lrecord, record);
                this.addUpdated(record);
            } catch (Exception e) {
                MessageHelper.setMessageError(e);
            }
        }
    }

    private void removefromlista(List<TarmSitioAlmacenamiento> ldata, TarmSitioAlmacenamiento abstractbean)
            throws Exception {
        int size = ldata.size();
        for (int i = 0; i < size; i++) {
            if (ldata.get(i).rowkey() == abstractbean.rowkey()) {
                ldata.remove(i);
                break;
            }
        }
    }

    /**
     * M&eacute;todo para el evento change del combo provincias
     */
    public void executeProvince() {
        lcantones = CantonController.find(record.getCountrycode(), record.getProvincecode());
        lparroquias = new ArrayList<>();
        lcities = new ArrayList<>();
    }

    /**
     * M&eacute;todo para el evento change del combo cantones
     */
    public void executeCanton() {
        if ((record.getCountrycode() != null) && (record.getCountrycode().compareTo("") != 0)) {
            lparroquias = ParroquiaController.find(record.getCountrycode(), record.getProvincecode(), record.getCantoncode());
            lcities = CityController.find(record.getCountrycode(), record.getProvincecode(), record.getCantoncode());
        }
    }

    /**
     * M&eacute;todo para el evento change del combo ciudad
     */
    public void executeCiudad() {
        if ((getRecord().getCantoncode() != null) && (getRecord().getCantoncode().compareTo("") != 0)) {
            List<TgeneCity> lcities = CityController.find(record.getCountrycode(), record.getProvincecode(), record.getCantoncode());
            setDireccionGoogleMap(lcities.get(0).getDescription() + ", " + "Ecuador");
        }
    }

    /**
     * M&eacute;todo para abrir el lov de persona
     */
    public void openPersonLov() {
        Map<String, List<String>> params = new HashMap<>();
        PersonLovController.openLov(params);
    }

    /**
     * M&eacute;todo para obtener la persona al cerrar el lov de persona
     *
     * @param event
     * @throws Exception
     */
    public void onReturnPersonLov(SelectEvent event) throws Exception {
        TcustPersonDetail tp = (TcustPersonDetail) event.getObject();
        super.addFilter("pk.personcode", tp.getPk().getPersoncode().toString());
        super.addField("nombre", tp.getName());
        super.addField("numeroDocumento", tp.getIdentification());
    }

    /**
     * M&eacute;todo para obtener la persona al cerrar el lov de persona
     *
     * @param event
     * @throws Exception
     */
    public void onReturnPersonDialogLov(SelectEvent event) throws Exception {
        TcustPersonDetail t = (TcustPersonDetail) event.getObject();
        record.getModifiedData().put("nombre", t.getName());
        record.getModifiedData().put("numeroDocumento", t.getIdentification());
        record.setPersoncode(t.getPk().getPersoncode());
    }

    /**
     * Entrega una lista de objetos TgeneCatalogDetail
     *
     * @param catalogcode C&oacute de cat&aacute;logo
     * @return lrecord Lista de objetos TgeneCatalogDetail
     */
    public static List<TarmSitioAlmacenamiento> find(String code) {
        try {
            SitioAlmacenamientoController cc = new SitioAlmacenamientoController();
            cc.init();
            cc.recperpage = 300;
            cc.addFilter("pk", code);
            cc.querydatabase();
            if ((cc.lrecord != null) && !cc.lrecord.isEmpty()) {
                return cc.lrecord;
            }
            return null;
        } catch (Throwable e) {
            MessageHelper.setMessageError(e);
            return null;
        }
    }

    /**
     * Metodo para recorreer los combos y setear las descripciones de lo q se
     * escoge para la vista
     *
     * @param list
     * @param codigo
     * @param pk
     */
    public void catalogos(List<TgeneCatalogDetail> list, String codigo, String pk) {
        for (TgeneCatalogDetail item : list) {
            if (codigo.equals(item.getPk().getCatalog())) {
                record.modifiedData.put(pk, item.getDescription());
                break;
            }
        }
    }

    /**
     * Metodo que permite setear los datos de coordenadas relacionados a la
     * entidad TarmDecomiso, una vez seleccionado un punto en el Map desde
     * pantalla
     */
    public void evento() {
        getRecord().setLatitud(new BigDecimal(getLatitud()));
        getRecord().setLongitud(new BigDecimal(getLongitud()));

        String longitudString = getRecord().getLongitud().toString();
        if (longitudString.contains("-")) {
            longitudString = longitudString.replace("-", "");
            setLongitudGMS("oeste");
        } else {
            setLongitudGMS("este");
        }
        String[] longitud = transformarGrados(longitudString);

        String latitudString = getRecord().getLatitud().toString();
        if (latitudString.contains("-")) {
            latitudString = latitudString.replace("-", "");
            setLatitudGMS("sur");
        } else {
            setLatitudGMS("norte");
        }
        String[] latitud = transformarGrados(latitudString);

        setLatitudG(latitud[0]);
        setLatitudM(latitud[1]);
        setLatitudS(latitud[2]);
        setLonguitudG(longitud[0]);
        setLonguitudM(longitud[1]);
        setLonguitudS(longitud[2]);
    }

    /**
     * Inicializa los campos al cambiar el tipo de Ubicacion desde la pagina
     */
    public void changeUbicacion() {
        getRecord().setLatitud(null);
        getRecord().setLongitud(null);
        setLatitudG("");
        setLatitudM("");
        setLatitudS("");
        setLonguitudG("");
        setLonguitudM("");
        setLonguitudS("");
        setLatitud("");
        setLongitud("");
        setLongitudGMS(null);
        setLatitudGMS(null);
    }

    /**
     * Permite inicializar los campos de longitud y lalitud y cargar a los datos
     * de coordenadas relacionados a la entidad TarmDecomiso
     */
    public void openMapPorCoordenandas() {
        setLatitud("");
        setLongitud("");
        if ("coodernadas".equals(tipoMapa)) {
            getRecord().setLatitud(new BigDecimal(transformarCoordenadas(latitudG, latitudM, latitudS, "sur".equals(latitudGMS))));
            getRecord().setLongitud(new BigDecimal(transformarCoordenadas(longuitudG, longuitudM, longuitudS, "oeste".equals(longitudGMS))));
        }
    }

    /**
     * Metodo que permite transformar de Coordenadas Hexadecimales a Coordenadas
     * en Grados, Minutos y Seguntos
     *
     * @param coordenada
     * @return vector con las Coordenadas en Grados, Minutos y Seguntos
     */
    public String[] transformarGrados(String coordenada) {
        int grados = new BigDecimal(coordenada).intValue();
        BigDecimal minutos = new BigDecimal(coordenada).subtract(new BigDecimal(grados)).multiply(new BigDecimal(60));
        int min = minutos.intValue();
        BigDecimal segundos = minutos.subtract(new BigDecimal(min)).multiply(new BigDecimal(60)).setScale(4, BigDecimal.ROUND_FLOOR);
        //System.out.println("latitude: " + grados + " " + min + " " + segundos);		
        return (grados + "," + min + "," + segundos).split(",");
    }

    public String transformarCoordenadas(String grados, String minutos, String segundos, boolean negativo) {
        BigDecimal resultado = new BigDecimal(grados).add(new BigDecimal(minutos).divide(new BigDecimal(60), 12, BigDecimal.ROUND_FLOOR)).add(new BigDecimal(segundos).divide(new BigDecimal(3600), 12, BigDecimal.ROUND_FLOOR));
        resultado = resultado.setScale(12, BigDecimal.ROUND_FLOOR);
        if (negativo) {
            resultado = resultado.multiply(new BigDecimal(-1));
        }
        return resultado.toString();
    }

    public List<TgeneProvince> getLprovinces() {
        return lprovinces;
    }

    public void setLprovinces(List<TgeneProvince> lprovinces) {
        this.lprovinces = lprovinces;
    }

    public List<TgeneCanton> getLcantones() {
        return lcantones;
    }

    public void setLcantones(List<TgeneCanton> lcantones) {
        this.lcantones = lcantones;
    }

    public List<TgeneParroquia> getLparroquias() {
        return lparroquias;
    }

    public void setLparroquias(List<TgeneParroquia> lparroquias) {
        this.lparroquias = lparroquias;
    }

    public List<TgeneCity> getLcities() {
        return lcities;
    }

    public void setLcities(List<TgeneCity> lcities) {
        this.lcities = lcities;
    }

    public List<TgeneCatalogDetail> getTipoComercio() {
        return tipoComercio;
    }

    public void setTipoComercio(List<TgeneCatalogDetail> tipoComercio) {
        this.tipoComercio = tipoComercio;
    }

    public Boolean getBtnEditar() {
        return btnEditar;
    }

    public void setBtnEditar(Boolean btnEditar) {
        this.btnEditar = btnEditar;
    }

    public String getLatitud() {
        return latitud;
    }

    public void setLatitud(String latitud) {
        this.latitud = latitud;
    }

    public String getLongitud() {
        return longitud;
    }

    public void setLongitud(String longitud) {
        this.longitud = longitud;
    }

    public String getDireccionGoogleMap() {
        return direccionGoogleMap;
    }

    public void setDireccionGoogleMap(String direccionGoogleMap) {
        this.direccionGoogleMap = direccionGoogleMap;
    }

    public String getTipoMapa() {
        return tipoMapa;
    }

    public void setTipoMapa(String tipoMapa) {
        this.tipoMapa = tipoMapa;
    }

    public String getLatitudG() {
        return latitudG;
    }

    public void setLatitudG(String latitudG) {
        this.latitudG = latitudG;
    }

    public String getLatitudM() {
        return latitudM;
    }

    public void setLatitudM(String latitudM) {
        this.latitudM = latitudM;
    }

    public String getLatitudS() {
        return latitudS;
    }

    public void setLatitudS(String latitudS) {
        this.latitudS = latitudS;
    }

    public String getLonguitudG() {
        return longuitudG;
    }

    public void setLonguitudG(String longuitudG) {
        this.longuitudG = longuitudG;
    }

    public String getLonguitudM() {
        return longuitudM;
    }

    public void setLonguitudM(String longuitudM) {
        this.longuitudM = longuitudM;
    }

    public String getLonguitudS() {
        return longuitudS;
    }

    public void setLonguitudS(String longuitudS) {
        this.longuitudS = longuitudS;
    }

    /**
     * @return the latitudGMS
     */
    public String getLatitudGMS() {
        return latitudGMS;
    }

    /**
     * @param latitudGMS the latitudGMS to set
     */
    public void setLatitudGMS(String latitudGMS) {
        this.latitudGMS = latitudGMS;
    }

    /**
     * @return the longitudGMS
     */
    public String getLongitudGMS() {
        return longitudGMS;
    }

    /**
     * @param longitudGMS the longitudGMS to set
     */
    public void setLongitudGMS(String longitudGMS) {
        this.longitudGMS = longitudGMS;
    }
}
