/*
 * 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 com.arrebol.taxiservicios.beans.dashboard;

import com.arrebol.taxiservicios.beans.TaxiGenericBean;
import com.arrebol.taxiservicios.controller.catalog.PaquetesController;
import com.arrebol.taxiservicios.controller.catalog.UserLocationController;
import com.arrebol.taxiservicios.controller.predio.LoteController;
import com.arrebol.taxiservicios.controller.predio.PredioController;
import com.arrebol.taxiservicios.model.catalog.LocationPaquetes;
import com.arrebol.taxiservicios.model.catalog.UserLocation;
import com.arrebol.taxiservicios.model.enums.GenericEnumType;
import com.arrebol.taxiservicios.model.predio.AbonoLote;
import com.arrebol.taxiservicios.model.predio.AbonoLoteDetalle;
import com.arrebol.taxiservicios.model.predio.AbonoLoteView;
import com.arrebol.taxiservicios.model.predio.AbonoProyecto;

import java.io.Serializable;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import javax.annotation.PostConstruct;
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.SelectEvent;
import org.primefaces.model.DefaultScheduleEvent;
import org.primefaces.model.LazyScheduleModel;
import org.primefaces.model.ScheduleEvent;
import org.primefaces.model.ScheduleModel;
import org.primefaces.model.chart.Axis;
import org.primefaces.model.chart.AxisType;
import org.primefaces.model.chart.BarChartModel;
import org.primefaces.model.chart.ChartSeries;
import org.primefaces.model.chart.LineChartModel;
import org.primefaces.model.chart.LineChartSeries;
import org.primefaces.model.chart.PieChartModel;

/**
 *
 * @author Picasso
 */
@Named("dashboardBean")
@ViewScoped
public class DashboardBean extends TaxiGenericBean implements Serializable {

    private PieChartModel pieModel1;
    private BarChartModel barModel;
    private LineChartModel lineModel1;
    private LineChartModel zoomModel;

    private LoteController loteController;
    private Long vencenTresDias;
    private Long vencidos;
    private Long vencenHoy;
    private Long pagadosHoy;
    private Date fechaHoy;
    private ScheduleModel lazyModel;
    private ScheduleEvent event = new DefaultScheduleEvent();
    final Logger logger = LogManager.getLogger(DashboardBean.class);
    private PredioController controladorPredio;
    private List<AbonoLote> abonosList;
    private List<AbonoLoteDetalle> listAbonoLoteDetalle;
    private List<AbonoLoteView> listAbonoLoteView;
    private Integer abonosPagadosHoy;
    private AbonoLote selectedabono;
    private String tipoBusquedaAbono;

    private UserLocationController userLocationController;
    private PaquetesController paquetesController;

    private Boolean AdvertenciaFinPaquete;
    private Integer noFinPaquete;

    private Date fechaInicial() {
        Calendar fechaMasUno = Calendar.getInstance();
        fechaMasUno.setTime(new Date());
        fechaMasUno.add(Calendar.DAY_OF_MONTH, 1);
        fechaMasUno.add(Calendar.HOUR, -7);
        return fechaMasUno.getTime();
    }

    private Date fechaVencidos() {
        Calendar fechaVencidos = Calendar.getInstance();
        fechaVencidos.setTime(new Date());
        //fechaVencidos.add(Calendar.DAY_OF_MONTH, 0);
        return fechaVencidos.getTime();
    }

    private Date fechaTresDiasDespues() {
        Calendar fechaTresDiasDespues = Calendar.getInstance();
        fechaTresDiasDespues.setTime(new Date());
        fechaTresDiasDespues.add(Calendar.DAY_OF_MONTH, 4);
        return fechaTresDiasDespues.getTime();
    }

    private void createPieModels() {
        createPieCobranza();
        createBarModels();
        createLineModels();
    }

    private void abonosVencidos() {
        setVencenTresDias(getLoteController().contarAbonoAVencerTresDias(fechaInicial(), fechaTresDiasDespues(), getLoggedUser().getLocation()));
        setVencidos(getLoteController().contarAbonosVencidos(fechaVencidos(), getLoggedUser().getLocation()));
        setVencenHoy(getLoteController().contarAbonosAvencerHoy(fechaInicial(), getLoggedUser().getLocation()));
        // se cargan el total de abonos y abonos detalles 
        Long noAbonosLote = getLoteController().contarAbonosPagadosHoy(fechaInicial(), getLoggedUser().getLocation());
        Long noAbonosLoteDetalle = getLoteController().contarAbonosDetallePagadosHoy(fechaInicial(), getLoggedUser().getLocation());        
        Long totalAbonos = noAbonosLote+noAbonosLoteDetalle;        
        setAbonosPagadosHoy(totalAbonos.intValue());
                
    }

    public void fillVencenTresDias() {
        setLoteController(new LoteController());
        setTipoBusquedaAbono("Abonos a vencer en 3 días");
        setAbonosList(getLoteController().fillAllAbonoAVencerTresDias(fechaInicial(), fechaTresDiasDespues(), getLoggedUser().getLocation()));
    }

    public void fillVencidos() {
        setLoteController(new LoteController());
        setTipoBusquedaAbono("Abonos a vencidos");
        setAbonosList(getLoteController().fillAllAbonosVencidos(fechaVencidos(), getLoggedUser().getLocation()));
    }

    public void fillPagadosHoy() {
        setLoteController(new LoteController());
        setTipoBusquedaAbono("Abonos pagados hoy");
        setListAbonoLoteView(getLoteController().fillAllAbonosAndAbonosDetallePagadosHoy(fechaInicial(), getLoggedUser().getLocation()));   
    }

    public void fillVencenHoy() {
        setLoteController(new LoteController());
        setTipoBusquedaAbono("Abonos que vencen hoy");
        setAbonosList(getLoteController().fillAllAbonosAvencerHoy(fechaInicial(), getLoggedUser().getLocation()));
    }

    private void createLineModels() {
        lineModel1 = initLinearModel();
        lineModel1.setTitle("Linear Chart");
        lineModel1.setLegendPosition("e");
        Axis yAxis = lineModel1.getAxis(AxisType.Y);
        yAxis.setMin(0);
        yAxis.setMax(10);

        zoomModel = initLinearModel();
        zoomModel.setTitle("Zoom");
        zoomModel.setZoom(true);
        zoomModel.setLegendPosition("e");
        yAxis = zoomModel.getAxis(AxisType.Y);
        yAxis.setMin(0);
        yAxis.setMax(10);
    }

    private LineChartModel initLinearModel() {
        LineChartModel model = new LineChartModel();

        LineChartSeries series1 = new LineChartSeries();
        series1.setLabel("Series 1");

        series1.set(1, 2);
        series1.set(2, 1);
        series1.set(3, 3);
        series1.set(4, 6);
        series1.set(5, 8);

        LineChartSeries series2 = new LineChartSeries();
        series2.setLabel("Series 2");

        series2.set(1, 6);
        series2.set(2, 3);
        series2.set(3, 2);
        series2.set(4, 7);
        series2.set(5, 9);

        model.addSeries(series1);
        model.addSeries(series2);

        return model;
    }

    private void createBarModels() {
        createBarModel();
    }

    private void createBarModel() {
        barModel = initBarModel();

        barModel.setTitle("Efectividad de cobranza mensual");
        barModel.setLegendPosition("ne");

        Axis xAxis = barModel.getAxis(AxisType.X);
        xAxis.setLabel("Meses");

        Axis yAxis = barModel.getAxis(AxisType.Y);
        yAxis.setLabel("Cobranza");
        yAxis.setMin(0);
        yAxis.setMax(200);
    }

    private BarChartModel initBarModel() {
        BarChartModel model = new BarChartModel();

        ChartSeries boys = new ChartSeries();
        boys.setLabel("Abonos esperados");
        boys.set("Febrero", 120);
        boys.set("Marzo", 100);
        boys.set("Abril", 44);
        boys.set("Mayo", 150);
        boys.set("Junio", 25);

        ChartSeries girls = new ChartSeries();
        girls.setLabel("Abonos recibidos");
        girls.set("Febrero", 52);
        girls.set("Marzo", 60);
        girls.set("Abril", 110);
        girls.set("Mayo", 135);
        girls.set("Junio", 120);

        model.addSeries(boys);
        model.addSeries(girls);

        return model;
    }

    private void createPieCobranza() {
        pieModel1 = new PieChartModel();

        Long disponible = getLoteController().contarLotesDisponibles(getLoggedUser().getLocation());
        Long apartado = getLoteController().contarLotesApartados(getLoggedUser().getLocation());
        Long vendido = getLoteController().contarLoteVendido(getLoggedUser().getLocation());
        Long liquidado = getLoteController().contarLoteLiquidado(getLoggedUser().getLocation());

        pieModel1.set("Inmuebles disponibles", disponible);
        pieModel1.set("Inmuebles vendidos", vendido);
        pieModel1.set("Inmuebles apartados", apartado);
        pieModel1.set("Inmuebles liquidados", liquidado);

        pieModel1.setTitle("Clasificación de Inmuebles");
        pieModel1.setSeriesColors("229954,00AAAA,FFAA00,9B59B6");
        pieModel1.setLegendPosition("w");
        pieModel1.setShadow(false);
    }

    private void createScheduler() {
        logger.info("createScheduler");
        try {

            setLazyModel(new LazyScheduleModel() {
                private static final long serialVersionUID = 1297279688835547588L;

                @Override
                public void loadEvents(Date start, Date end) {

                    List<AbonoProyecto> abonosProyectosLista = getControladorPredio().buscarAbonosProyectos(getLoggedUser().getLocation());

                    abonosProyectosLista.forEach((AbonoProyecto abonoProyecto) -> {
                        if (null != abonoProyecto.getFechaAPagar()) {
                            DefaultScheduleEvent ev = new DefaultScheduleEvent();

                            Calendar c = Calendar.getInstance();
                            c.setTime(abonoProyecto.getFechaAPagar());
                            c.add(Calendar.DATE, 1);
                            c.set(Calendar.HOUR_OF_DAY, 0);
                            c.set(Calendar.MINUTE, 0);
                            c.set(Calendar.SECOND, 0);
                            c.set(Calendar.MILLISECOND, 0);

                            ev.setData(abonoProyecto.getPago());
                            ev.setDescription(abonoProyecto.getPredio().getPropetiario().getFirstName() + "\n " + abonoProyecto.getPredio().getPropetiario().getLastName());
                            ev.setStartDate(c.getTime());
                            ev.setEndDate(c.getTime());
                            ev.setAllDay(true);
                            ev.setTitle(abonoProyecto.getPredio().getPropetiario().getFirstName() + " " + abonoProyecto.getPredio().getPropetiario().getSecondName() + " " + abonoProyecto.getPredio().getPropetiario().getMiddleName() + " " + abonoProyecto.getPredio().getPropetiario().getLastName() + "-" + abonoProyecto.getPredio().getNombreProyecto());
                            ev.setStyleClass(validadorStyleClass(abonoProyecto.getFechaAPagar(), abonoProyecto.getPagoEstatus()));

                            lazyModel.addEvent(ev);
                        }
                    });
                }
            });

        } catch (Exception e) {
            logger.error("createScheduler", e);
            setLazyModel(new LazyScheduleModel() {
                private static final long serialVersionUID = 3109256773218160485L;
            });
        }
    }

    public void onEventSelect(SelectEvent selectEvent) {
        event = (ScheduleEvent) selectEvent.getObject();
    }

    public String validadorStyleClass(Date fechaPago, GenericEnumType estatus) {
        if (estatus.equals(GenericEnumType.ENABLED)) {
            return "datatableRowGreen";
        } else if (fechaPago.before(fechaHoy)) {
            return "datatableRowEmpty";
        } else {

            return "";
        }
    }

    @PostConstruct
    public void init() {
        setLoteController(new LoteController());
        setControladorPredio(new PredioController());
        fechaHoy = new Date();
        setTipoBusquedaAbono("");
        List<AbonoLote> ab = null;
        setAbonosList(ab);
        abonosVencidos();
        createPieModels();
        createScheduler();
        setAdvertenciaFinPaquete(false);
        // Validasion del pago automatico
        setUserLocationController(new UserLocationController());
        List<UserLocation> userLocation = getUserLocationController().fillAllUserLocationByUser(getLoggedUser());
        if (userLocation.get(0).getPagoAutomatico().hashCode() == 1) {            
            setPaquetesController(new PaquetesController());
            List<LocationPaquetes> listLocationPaquetes = getPaquetesController().fillAllLocationPaquetesByLocation(getLoggedUser().getLocation());
            // Se verifican cuantos días faltan para qué termine el paquete activo 
            Date fecha2Date = listLocationPaquetes.get(0).getFechaFin();
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(fecha2Date);
            calendar.add(Calendar.DAY_OF_MONTH, 1);  // Restar 6 horas
            Date fecha2DateR = calendar.getTime();           
            LocalDate fecha1LocalDate = LocalDate.now();
            LocalDate fecha2LocalDate = fecha2DateR.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
            long diasDeDiferencia = ChronoUnit.DAYS.between(fecha1LocalDate, fecha2LocalDate);
            if((int) diasDeDiferencia<=3){
                setAdvertenciaFinPaquete(true);
            }
            setNoFinPaquete((int) diasDeDiferencia);
        }
    }

    public PieChartModel getPieModel1() {
        return pieModel1;
    }

    public void setPieModel1(PieChartModel pieModel1) {
        this.pieModel1 = pieModel1;
    }

    public BarChartModel getBarModel() {
        return barModel;
    }

    public void setBarModel(BarChartModel barModel) {
        this.barModel = barModel;
    }

    public LineChartModel getLineModel1() {
        return lineModel1;
    }

    public void setLineModel1(LineChartModel lineModel1) {
        this.lineModel1 = lineModel1;
    }

    public LineChartModel getZoomModel() {
        return zoomModel;
    }

    public void setZoomModel(LineChartModel zoomModel) {
        this.zoomModel = zoomModel;
    }

    public LoteController getLoteController() {
        return loteController;
    }

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

    public Long getVencenTresDias() {
        return vencenTresDias;
    }

    public void setVencenTresDias(Long vencenTresDias) {
        this.vencenTresDias = vencenTresDias;
    }

    public Long getVencidos() {
        return vencidos;
    }

    public void setVencidos(Long vencidos) {
        this.vencidos = vencidos;
    }

    public Long getVencenHoy() {
        return vencenHoy;
    }

    public void setVencenHoy(Long vencenHoy) {
        this.vencenHoy = vencenHoy;
    }

    public Long getPagadosHoy() {
        return pagadosHoy;
    }

    public void setPagadosHoy(Long pagadosHoy) {
        this.pagadosHoy = pagadosHoy;
    }

    public ScheduleModel getLazyModel() {
        return lazyModel;
    }

    public void setLazyModel(ScheduleModel lazyModel) {
        this.lazyModel = lazyModel;
    }

    public ScheduleEvent getEvent() {
        return event;
    }

    public void setEvent(ScheduleEvent event) {
        this.event = event;
    }

    public PredioController getControladorPredio() {
        return controladorPredio;
    }

    public void setControladorPredio(PredioController controladorPredio) {
        this.controladorPredio = controladorPredio;
    }

    public Date getFechaHoy() {
        return fechaHoy;
    }

    public void setFechaHoy(Date fechaHoy) {
        this.fechaHoy = fechaHoy;
    }

    public List<AbonoLote> getAbonosList() {
        return abonosList;
    }

    public void setAbonosList(List<AbonoLote> abonosList) {
        this.abonosList = abonosList;
    }

    public String getTipoBusquedaAbono() {
        return tipoBusquedaAbono;
    }

    public void setTipoBusquedaAbono(String tipoBusquedaAbono) {
        this.tipoBusquedaAbono = tipoBusquedaAbono;
    }

    public AbonoLote getSelectedabono() {
        return selectedabono;
    }

    public void setSelectedabono(AbonoLote selectedabono) {
        this.selectedabono = selectedabono;
    }

    public UserLocationController getUserLocationController() {
        return userLocationController;
    }

    public void setUserLocationController(UserLocationController userLocationController) {
        this.userLocationController = userLocationController;
    }

    public PaquetesController getPaquetesController() {
        return paquetesController;
    }

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

    public Boolean getAdvertenciaFinPaquete() {
        return AdvertenciaFinPaquete;
    }

    public void setAdvertenciaFinPaquete(Boolean AdvertenciaFinPaquete) {
        this.AdvertenciaFinPaquete = AdvertenciaFinPaquete;
    }

    public Integer getNoFinPaquete() {
        return noFinPaquete;
    }

    public void setNoFinPaquete(Integer noFinPaquete) {
        this.noFinPaquete = noFinPaquete;
    }

    public List<AbonoLoteDetalle> getListAbonoLoteDetalle() {
        return listAbonoLoteDetalle;
    }

    public void setListAbonoLoteDetalle(List<AbonoLoteDetalle> listAbonoLoteDetalle) {
        this.listAbonoLoteDetalle = listAbonoLoteDetalle;
    }

    public List<AbonoLoteView> getListAbonoLoteView() {
        return listAbonoLoteView;
    }

    public void setListAbonoLoteView(List<AbonoLoteView> listAbonoLoteView) {
        this.listAbonoLoteView = listAbonoLoteView;
    }

    public Integer getAbonosPagadosHoy() {
        return abonosPagadosHoy;
    }

    public void setAbonosPagadosHoy(Integer abonosPagadosHoy) {
        this.abonosPagadosHoy = abonosPagadosHoy;
    }

}
