/*
 * Arrebol Consultancy copyright.
 * 
 * This code belongs to Arrebol Consultancy
 * its use, redistribution or modification are prohibited 
 * without written authorization from Arrebol Consultancy.
 */
package com.arrebol.taxiservicios.beans.predio;

import com.arrebol.taxiservicios.beans.TaxiGenericBean;
import com.arrebol.taxiservicios.controller.admin.GenericPersonController;
import com.arrebol.taxiservicios.controller.catalog.LocationController;
import com.arrebol.taxiservicios.controller.catalog.PaquetesController;
import com.arrebol.taxiservicios.controller.predio.LoteController;
import com.arrebol.taxiservicios.controller.predio.PredioController;
import com.arrebol.taxiservicios.model.catalog.Location;
import com.arrebol.taxiservicios.model.catalog.LocationPaquetes;
import com.arrebol.taxiservicios.model.core.Person;
import com.arrebol.taxiservicios.model.enums.CompromisoPago;
import com.arrebol.taxiservicios.model.enums.EstatusLote;
import com.arrebol.taxiservicios.model.enums.GenericEnumType;
import com.arrebol.taxiservicios.model.enums.PeriodoPago;
import com.arrebol.taxiservicios.model.enums.PersonType;
import com.arrebol.taxiservicios.model.enums.TipoAbono;
import com.arrebol.taxiservicios.model.enums.TipoProyecto;
import com.arrebol.taxiservicios.model.predio.AbonoProyecto;
import com.arrebol.taxiservicios.model.predio.Lote;
import com.arrebol.taxiservicios.model.predio.Manzana;
import com.arrebol.taxiservicios.model.predio.Predio;
import com.arrebol.taxiservicios.model.predio.proyectosLotesView;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.view.ViewScoped;
import javax.inject.Named;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.primefaces.event.FlowEvent;
import org.primefaces.event.RowEditEvent;

/**
 *
 * @author Carlos Janitzio Zavala Lopez <janitzio.zavala@arrebol.com.mx>
 */
@Named("predioListBean")
@ViewScoped
public class PredioListBean extends TaxiGenericBean implements Serializable {

    private static final long serialVersionUID = -7284027390656669184L;
    final Logger logger = LogManager.getLogger(getClass());
    private List<Predio> predio;
    private List<proyectosLotesView> proyectosLotesList;
    private List<Manzana> manzana;
    private Manzana selectedManzana;
    private proyectosLotesView selectedPredio;
    private Predio newPredio;
    private PredioController controller;
    private LocationController locationController;
    private List<Location> locations;
    private String personId;
    private Location location;
    private Person propietario;
    private GenericPersonController personController;
    private String compromisoPago;
    private PaquetesController paquetesController;
    private boolean skip;
    private Boolean limiteProyectos;
    private Integer numLotes;
    private LoteController loteController;
    private String tipoProyecto;
    private List<Person> providers;
    private Person provider;
    private Date sixteenYearsOld;
    private String firstNameProvider;
    private String abreviacionProyecto;

    public boolean isSkip() {
        return skip;
    }

    public void setSkip(boolean skip) {
        this.skip = skip;
    }

    public String onFlowProcess(FlowEvent event) {
        if (skip) {
            skip = false; //reset in case user goes back
            return "confirm";
        } else {
            return event.getNewStep();
        }
    }

    public void addManzana() {
        logger.info("addManzana");

        Manzana manzanaNueva = new Manzana();

        manzanaNueva.setId(UUID.randomUUID().toString());
        getManzana().add(manzanaNueva);

    }

    public void editRowManzana(RowEditEvent event) {
        try {
            Manzana p = (Manzana) event.getObject();

            getManzana().forEach((Manzana manzanaTemp) -> {
                if (p.getId().equals(manzanaTemp.getId())) {
                    manzanaTemp.setNombre(p.getNombre());
                    manzanaTemp.setNumLotes(p.getNumLotes());
                }
            });

        } catch (Exception e) {
            logger.error("editRow: " + e);
            showMessage(FacesMessage.SEVERITY_FATAL, "Compras",
                    "Error al editar el producto");
        }

    }

    public void deleteSelectedProduct() {
        logger.info("deleteSelectedProduct");
        try {
            getManzana().remove(getSelectedManzana());

        } catch (Exception e) {
            logger.error("deleteSelectedProduct", e);
            showMessage(FacesMessage.SEVERITY_FATAL,
                    getBundlePropertyFile().getString("garage.title"),
                    getBundlePropertyFile().getString("fatal.access.details"));
        }
    }

    public void addRow() {
        logger.info("addRow");
        try {
                // Validación del paquete 
                setPaquetesController(new PaquetesController());
                setLoteController(new LoteController());
                List<LocationPaquetes> Lpack = getPaquetesController().fillAllLocationPaquetesByLocationAndEstatusActivo(getLoggedUser().getLocation(), GenericEnumType.ENABLED);
                // Se cuentan el número de lotes que se pretende insertar
                setNumLotes(0);
                getManzana().forEach((Manzana manzanaTemp) -> {
                    for (int i = 0; i < manzanaTemp.getNumLotes(); i++) {
                        setNumLotes(getNumLotes() + 1);
                    }
                });
                // Se carga la cantidad de lotes existentes 
                Long lotesExistentes = getLoteController().contarLotesByLocation(getLoggedUser().getLocation());
                // Lotes totales 
                Integer lotesTotales = lotesExistentes.intValue() + getNumLotes();
                Integer difLotes = Lpack.get(0).getPaquete().getNumeroLotes() - lotesExistentes.intValue();
                if (lotesTotales <= Lpack.get(0).getPaquete().getNumeroLotes()) {
                    newPredio.setId(UUID.randomUUID().toString());
                    newPredio.setPropetiario(new Person(personId));
                    newPredio.setLocation(getLoggedUser().getLocation());
                    newPredio.setEstatusActivo(GenericEnumType.ENABLED);
                    newPredio.setAbreviatura(getAbreviacionProyecto());

                    switch (getCompromisoPago()) {
                        case "MENSUAL":
                            newPredio.setCompromisoPago(CompromisoPago.MENSUAL);
                            break;
                        case "ANUAL":
                            newPredio.setCompromisoPago(CompromisoPago.ANUAL);
                            break;
                        case "TRIMESTRAL":
                            newPredio.setCompromisoPago(CompromisoPago.TRIMESTRAL);
                            break;
                        default:
                            break;
                    }

                    switch (getTipoProyecto()) {
                        case "Lotes":
                            newPredio.setTipoProyecto(TipoProyecto.LOTE);
                            break;
                        case "Viviendas":
                            newPredio.setTipoProyecto(TipoProyecto.VIVIENDA);
                            break;
                        case "Departamentos":
                            newPredio.setTipoProyecto(TipoProyecto.DEPARTAMENTO);
                            break;
                        case "Oficinas":
                            newPredio.setTipoProyecto(TipoProyecto.OFICINA);
                            break;
                        default:
                            break;
                    }

                    boolean success = getController().addPredio(newPredio, getLoggedUser(), true);

                    if (getNewPredio().getAnticipo() > 0) {
                        AbonoProyecto abono = new AbonoProyecto();
                        abono.setPredio(getNewPredio());
                        abono.setTipoAbono(TipoAbono.ANTICIPO);
                        abono.setEstatusActivo(GenericEnumType.ENABLED);
                        abono.setPagoEstatus(GenericEnumType.DISABLED);
                        abono.setFechaAPagar(getNewPredio().getCreatedOn());
                        abono.setPago(getNewPredio().getAnticipo());
                        abono.setSaldoAnterior(getNewPredio().getCosto());
                        abono.setSaldoNuevo(getNewPredio().getCosto() - getNewPredio().getAnticipo());

                        getController().addAbonoProyecto(abono, getLoggedUser(), true);

                    }

                    if (success) {

                        getManzana().forEach((Manzana manzanaTemp) -> {

                            manzanaTemp.setCreatedBy(getLoggedUser());
                            manzanaTemp.setPredio(newPredio);

                            boolean successManzana = getController().addManzana(manzanaTemp, getLoggedUser(), true);

                            if (successManzana) {
                                for (int i = 0; i < manzanaTemp.getNumLotes(); i++) {
                                    Lote lote = new Lote();
                                    lote.setId(UUID.randomUUID().toString());
                                    lote.setManzana(manzanaTemp);
                                    lote.setEstatusLote(EstatusLote.DISPONIBLE);
                                    lote.setPeriodoPago(PeriodoPago.MENSUAL);
                                    boolean succesLote = getController().addLote(lote, getLoggedUser(), true);
                                }
                            }
                        });
                    }
                    showMessage(FacesMessage.SEVERITY_INFO, "Proyecto", "Proyecto creado con exito");
                    init();
                } else {
                    if (difLotes < 0) {
                        showMessage(FacesMessage.SEVERITY_ERROR, "Error", "No puede insertar más lotes deacuerdo al paquete asociado a la locación actual.");
                    } else {
                        showMessage(FacesMessage.SEVERITY_ERROR, "Error", "Solo puede insertar " + difLotes + " lotes más deacuerdo al paquete asociado a la locación actual.");
                    }
                }

        } catch (Exception e) {
            showMessage(FacesMessage.SEVERITY_ERROR, "Proyecto", "Hubo un error");
        }

    }

    public void deleteSelectedPredioEstatus() {

        logger.info("updateLote");

        try {
            setController(new PredioController());
            Predio pre = getController().fillPredioDatatableByid(getSelectedPredio().getId());
            pre.setLastUpdatedOn(new Date());
            pre.setEstatusActivo(GenericEnumType.DISABLED);
            getController().addPredio(pre, getLoggedUser(), false);
            getController().deleteManzanaByPredio(pre, getLoggedUser());
            getController().deleteLoteByPredio(pre, getLoggedUser());
            getController().deleteAbonoLoteByPredio(pre, getLoggedUser());
            getController().deleteAbonoProyectoByPredio(pre, getLoggedUser());

            showMessage(FacesMessage.SEVERITY_INFO, "Predio",
                    "Predio eliminado correctamente");

            setProyectosLotesList(getController().fillProyectosLotesView(getLoggedUser().getLocation()));
            setSelectedPredio(null);

        } catch (Exception e) {

        }

    }

    public void addProvider() {
        logger.info("addProvider");
        try {

            getProvider().setId(UUID.randomUUID().toString());
            getProvider().setActive(true);
            getProvider().setRoot(false);
            getProvider().setCreatedOn(new Date());
            getProvider().setLocation(new Location(getLoggedUser().getLocation().getId()));

            boolean success = getController().addPerson(getProvider(), getLoggedUser().getUserName(), true);

            if (success) {

                showMessage(FacesMessage.SEVERITY_INFO,
                        getBundlePropertyFile().getString("provider.add.title"),
                        getBundlePropertyFile().getString("provider.add.success.desc"));
                setProviders(getController().fillProviderComboBox(getLoggedUser().getLocation()));

            } else {
                logger.error("Provider " + getProvider() + " was not saved");
                showMessage(FacesMessage.SEVERITY_ERROR,
                        getBundlePropertyFile().getString("provider.add.title"),
                        getBundlePropertyFile().getString("provider.add.fail.desc"));
            }
        } catch (Exception e) {
            logger.error("addProvider: " + e);
            showMessage(FacesMessage.SEVERITY_FATAL,
                    getBundlePropertyFile().getString("provider.add.title"),
                    getBundlePropertyFile().getString("provider.add.exception.desc"));
        }
        setProvider(new Person(PersonType.PROVIDER));
    }

    public Person getPersonMonstrar() {

        return getPersonController().getPersonById(personId);

    }

    public Location getLocationMonstrar() {
        return getLocationController().getLocationById(getLoggedUser().getLocation().getId());

    }

    @PostConstruct
    public void init() {
        try {
            loadBundlePropertyFile();
            setController(new PredioController());
            setLocationController(new LocationController());
            setPersonController(new GenericPersonController() {
            });
            setLocations(getLocationController().fillLocationDatatable());
            setProyectosLotesList(getController().fillProyectosLotesView(getLoggedUser().getLocation()));
            setProviders(getController().fillProviderComboBox(getLoggedUser().getLocation()));
            setNewPredio(new Predio());
            getNewPredio().setCosto(0D);
            getNewPredio().setAnticipo(0D);
            getNewPredio().setInteresMensual(0D);
            getNewPredio().setMandado(0D);
            getNewPredio().setCobranzaAtraso(0D);
            getNewPredio().setComisionMensual(0D);
            setManzana(new ArrayList<>());
            // se valida el numero de proyectos 
            setController(new PredioController());
            setPaquetesController(new PaquetesController());
            List<LocationPaquetes> Lpack = getPaquetesController().fillAllLocationPaquetesByLocationAndEstatusActivo(getLoggedUser().getLocation(), GenericEnumType.ENABLED);
            setController(new PredioController());
            List<proyectosLotesView> numPredios = getController().fillProyectosLotesView(location);
            if (numPredios.size() < Lpack.get(0).getPaquete().getNumeroProyectos()) {
                setLimiteProyectos(true);
            } else {
                setLimiteProyectos(false);
            }

            Calendar calendar = Calendar.getInstance();

            calendar.add(Calendar.YEAR, -15);
            setSixteenYearsOld(calendar.getTime());
            setProvider(new Person(PersonType.PROVIDER));

        } catch (Exception e) {
            logger.error("Customer init", e);
        }
    }

    public List<Predio> getPredio() {
        return predio;
    }

    public void setPredio(List<Predio> predio) {
        this.predio = predio;
    }

    public proyectosLotesView getSelectedPredio() {
        return selectedPredio;
    }

    public void setSelectedPredio(proyectosLotesView selectedPredio) {
        this.selectedPredio = selectedPredio;
    }

    public PredioController getController() {
        return controller;
    }

    public void setController(PredioController controller) {
        this.controller = controller;
    }

    public LocationController getLocationController() {
        return locationController;
    }

    public void setLocationController(LocationController locationController) {
        this.locationController = locationController;
    }

    public List<Location> getLocations() {
        return locations;
    }

    public void setLocations(List<Location> locations) {
        this.locations = locations;
    }

    public Predio getNewPredio() {
        return newPredio;
    }

    public void setNewPredio(Predio newPredio) {
        this.newPredio = newPredio;
    }

    public void setProviders(List<Person> providers) {
        this.providers = providers;
    }

    public List<Person> getProviders() {
        return providers;
    }

    public String getPersonId() {
        return personId;
    }

    public void setPersonId(String personId) {
        this.personId = personId;
    }

    public List<Manzana> getManzana() {
        return manzana;
    }

    public void setManzana(List<Manzana> manzana) {
        this.manzana = manzana;
    }

    public Manzana getSelectedManzana() {
        return selectedManzana;
    }

    public void setSelectedManzana(Manzana selectedManzana) {
        this.selectedManzana = selectedManzana;
    }

    public Location getLocation() {
        return location;
    }

    public void setLocation(Location location) {
        this.location = location;
    }

    public Person getPropietario() {
        return propietario;
    }

    public void setPropietario(Person propietario) {
        this.propietario = propietario;
    }

    public GenericPersonController getPersonController() {
        return personController;
    }

    public void setPersonController(GenericPersonController personController) {
        this.personController = personController;
    }

    public String getCompromisoPago() {
        return compromisoPago;
    }

    public void setCompromisoPago(String compromisoPago) {
        this.compromisoPago = compromisoPago;
    }

    public List<proyectosLotesView> getProyectosLotesList() {
        return proyectosLotesList;
    }

    public void setProyectosLotesList(List<proyectosLotesView> proyectosLotesList) {
        this.proyectosLotesList = proyectosLotesList;
    }

    public PaquetesController getPaquetesController() {
        return paquetesController;
    }

    public void setPaquetesController(PaquetesController paquetesController) {
        this.paquetesController = paquetesController;
    }

    public Boolean getLimiteProyectos() {
        return limiteProyectos;
    }

    public void setLimiteProyectos(Boolean limiteProyectos) {
        this.limiteProyectos = limiteProyectos;
    }

    public Integer getNumLotes() {
        return numLotes;
    }

    public void setNumLotes(Integer numLotes) {
        this.numLotes = numLotes;
    }

    public LoteController getLoteController() {
        return loteController;
    }

    public void setLoteController(LoteController loteController) {
        this.loteController = loteController;
    }

    public String getTipoProyecto() {
        return tipoProyecto;
    }

    public void setTipoProyecto(String tipoProyecto) {
        this.tipoProyecto = tipoProyecto;
    }

    public Person getProvider() {
        return provider;
    }

    public void setProvider(Person provider) {
        this.provider = provider;
    }

    public Date getSixteenYearsOld() {
        return sixteenYearsOld;
    }

    public void setSixteenYearsOld(Date sixteenYearsOld) {
        this.sixteenYearsOld = sixteenYearsOld;
    }

    public String getFirstNameProvider() {
        return firstNameProvider;
    }

    public void setFirstNameProvider(String firstNameProvider) {
        this.firstNameProvider = firstNameProvider;
    }

    public String getAbreviacionProyecto() {
        return abreviacionProyecto;
    }

    public void setAbreviacionProyecto(String abreviacionProyecto) {
        this.abreviacionProyecto = abreviacionProyecto;
    }

}
