/*
 * 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.admin.taxi;

import com.arrebol.taxiservicios.beans.TaxiGenericBean;
import com.arrebol.taxiservicios.controller.admin.ReleaseResourceController;
import com.arrebol.taxiservicios.controller.admin.TaxiController;
import com.arrebol.taxiservicios.controller.util.DateWrapper;
import com.arrebol.taxiservicios.model.admin.Contract;
import com.arrebol.taxiservicios.model.admin.ReleaseResource;
import com.arrebol.taxiservicios.model.admin.Service;
import com.arrebol.taxiservicios.model.admin.Taxi;
import com.arrebol.taxiservicios.model.catalog.Color;
import com.arrebol.taxiservicios.model.catalog.Vehicle;
import com.arrebol.taxiservicios.model.core.Person;
import com.arrebol.taxiservicios.model.core.User;
import com.arrebol.taxiservicios.model.enums.BasicType;
import com.arrebol.taxiservicios.model.enums.GenericEnumType;
import com.arrebol.taxiservicios.model.enums.PlatformType;
import com.arrebol.taxiservicios.wrapper.ContractTaxiTreeNodeWrapper;
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.model.DefaultTreeNode;
import org.primefaces.model.DualListModel;
import org.primefaces.model.TreeNode;

/**
 *
 * @author oscar vargas
 */
@Named("taxiAddBean")
@ViewScoped
public class TaxiAddBean extends TaxiGenericBean implements Serializable {

    public void addWeekWork() {
        logger.info("addWeekWork");
        try {
            if (isMonday() || isTuesday() || isWednesday() || isThursday() || isFriday() || isSaturday() || isSunday()) {
                PlatformType platformType = null;

                for (PlatformType pf : PlatformType.values()) {
                    if (getPlatform().equals(pf.toString())) {
                        platformType = pf;
                        break;
                    }
                }

                if (getController().updateWeekWorkTaxiById(getTaxi().getId(), getLoggedUser().getId(), platformType,
                        isMonday(), isTuesday(), isWednesday(), isThursday(), isFriday(), isSaturday(), isSunday())) {
                    showMessage(FacesMessage.SEVERITY_INFO,
                            getBundlePropertyFile().getString("taxi.add.title"),
                            getBundlePropertyFile().getString("taxi.add.week.work.success.desc"));
                } else {
                    logger.error("addWeekWork: error week work.");
                    showMessage(FacesMessage.SEVERITY_ERROR,
                            getBundlePropertyFile().getString("taxi.add.title"),
                            getBundlePropertyFile().getString("taxi.add.exception.desc"));
                }
            } else {
                logger.error("addWeekWork: select at lease one day of te week.");
                showMessage(FacesMessage.SEVERITY_ERROR,
                        getBundlePropertyFile().getString("taxi.add.title"),
                        getBundlePropertyFile().getString("taxi.add.week.work.exception.desc"));
            }
        } catch (Exception e) {
            logger.error("addWeekWork: " + e);
            showMessage(FacesMessage.SEVERITY_FATAL,
                    getBundlePropertyFile().getString("taxi.add.title"),
                    getBundlePropertyFile().getString("taxi.add.exception.desc"));
        }
    }

    /**
     * Save/Update an taxi in the system.
     */
    public void addTaxi() {
        logger.info("addTaxi");
        try {
            Person oldDriver = null;

            if (!isAddTaxiBtnOnclick()) {
                getTaxi().setId(UUID.randomUUID().toString());
                getTaxi().setActive(true);
                getTaxi().setCreatedOn(new Date());
                getTaxi().setLocation(getLoggedUser().getLocation());
            } else {
                getTaxi().setLastUpdatedOn(new Date());

                Taxi tmp = getController().getDriverByTaxiId(getTaxi().getId());

                if (null != tmp && null != tmp.getDriver()) {
                    oldDriver = tmp.getDriver();
                }
            }
            
            if(gps)
            {
                getTaxi().setGps(BasicType.ENEBLED);
            }
            else
            {
                getTaxi().setGps(BasicType.DISABLED);
            }
            
            if(apc)
            {
                getTaxi().setApc(BasicType.ENEBLED);
            }
            else
            {
                getTaxi().setApc(BasicType.DISABLED);
            }

            boolean success = getController().addTaxi(getTaxi(), getLoggedUser().getId(), !isAddTaxiBtnOnclick(), vehicleId, driverId, customerId, colorId);

            if (success) {
                releaseResource(oldDriver);

                setAddTaxiBtnOnclick(true);
                showMessage(FacesMessage.SEVERITY_INFO,
                        getBundlePropertyFile().getString("taxi.add.title"),
                        getBundlePropertyFile().getString("taxi.add.success.desc"));
            } else {
                logger.error("Taxi " + getTaxi() + " was not " + (isAddTaxiBtnOnclick() ? "updated" : "saved"));
                showMessage(FacesMessage.SEVERITY_ERROR,
                        getBundlePropertyFile().getString("taxi.add.title"),
                        getBundlePropertyFile().getString("taxi.add.fail.desc"));
            }
        } catch (Exception e) {
            logger.error("addTaxi: " + e);
            showMessage(FacesMessage.SEVERITY_FATAL,
                    getBundlePropertyFile().getString("taxi.add.title"),
                    getBundlePropertyFile().getString("taxi.add.exception.desc"));
        }
    }

    /**
     * Create a contract with all selected services for the current taxi.
     */
    public void saveContract() {
        logger.info("saveContract");
        try {
            List<Service> target = new ArrayList<>();
            float price = 0f;

            for (Service service : getServices().getTarget()) {
                if (!service.isDisable()) {
                    target.add(service);
                    price = price + service.getCharge();
                }
            }

            if (!target.isEmpty()) {
                Calendar calendar = Calendar.getInstance();

                calendar.setTime(getStartDate());
                calendar.add(Calendar.YEAR, 1);

                setContract(new Contract());

                getContract().setId(UUID.randomUUID().toString());
                getContract().setStartDate(getStartDate());
                getContract().setEndDate(calendar.getTime());
                getContract().setPrice(price);
                getContract().setActive(true);
                getContract().setTaxi(new Taxi(getTaxi().getId()));
                getContract().setCreatedOn(new Date());
                getContract().setName(getTaxi().getEconomicNumber()
                        + " - "
                        + (numberContract++));
                getContract().setCreatedBy(
                        new User(
                                getLoggedUser().getId(), getLoggedUser().getUserName()
                        )
                );

                boolean success = getController().saveContract(getContract(), target);

                if (success) {
                    getServices().getTarget().forEach((Service srv) -> {
                        srv.setDisable(true);
                    });
                    setAddContractsBtnOnclick(true);
                    fillTreeTable(target);
                    showMessage(FacesMessage.SEVERITY_INFO,
                            getBundlePropertyFile().getString("taxi.contract.add.title"),
                            getBundlePropertyFile().getString("taxi.contract.add.success.desc"));
                } else {
                    logger.error("Contract was not saved " + contract);
                    showMessage(FacesMessage.SEVERITY_ERROR,
                            getBundlePropertyFile().getString("taxi.contract.add.title"),
                            getBundlePropertyFile().getString("taxi.contract.add.fail.desc"));
                }
            } else {
                showMessage(FacesMessage.SEVERITY_ERROR,
                        getBundlePropertyFile().getString("taxi.contract.add.title"),
                        getBundlePropertyFile().getString("empty.contract"));
            }
        } catch (Exception e) {
            logger.error("saveContract: " + e);
            showMessage(FacesMessage.SEVERITY_FATAL,
                    getBundlePropertyFile().getString("taxi.contract.add.title"),
                    getBundlePropertyFile().getString("taxi.contract.add.exception.desc"));
        }
    }

    public void printContracts() {

    }

    /**
     *
     * @param oldDriver
     */
    private void releaseResource(Person oldDriver) {
        try {
            Date date = DateWrapper.getTodayMXTime();

            ReleaseResource oldDriverRR = new ReleaseResource(UUID.randomUUID().toString(), oldDriver, date, GenericEnumType.ENABLED, getLoggedUser(), date);
            ReleaseResource taxiToRelease = new ReleaseResource(UUID.randomUUID().toString(), getTaxi(), date, GenericEnumType.ENABLED, getLoggedUser(), date);

            if (!isAddTaxiBtnOnclick()) {
                // Si nuevo taxi se crea con chofer,el chofer estatus = DISABLED de los choferes liberados
                if (null != getDriverId() && !"".equals(getDriverId())) {
                    getReleaseResourceController().updateReleaseResourceDetails(new Person(getDriverId()), null, date, GenericEnumType.DISABLED, getLoggedUser(), date);
                } else {
                    //Significa que se crea un taxi pero no se le asigno chofer, por lo que el taxi estatus = ENABLED
                    getReleaseResourceController().saveReleaseResource(taxiToRelease);
                }
            } else {
                // ENABLED  = Poner en banca = Insert
                // DISABLED = Sacar de banca = Update
                /**
                 * Si no tenia chofer previo y ahora si tiene chofer: TAXI =
                 * DISABLED and CHOFER = DISABLED
                 */
                if (null == oldDriver && (null != getDriverId() && !"".equals(getDriverId()))) {
                    getReleaseResourceController().updateReleaseResourceDetails(null, getTaxi(), date, GenericEnumType.DISABLED, getLoggedUser(), date);
                    getReleaseResourceController().updateReleaseResourceDetails(new Person(getDriverId()), null, date, GenericEnumType.DISABLED, getLoggedUser(), date);
                } /**
                 * Tenia chofer viejo, pero ahora ya no va a tener chofer chofer
                 * viejo = ENABLED, taxi = ENABLED
                 */
                else if ((null == getDriverId() || "".equals(getDriverId())) && null != oldDriver) {
                    getReleaseResourceController().saveReleaseResource(oldDriverRR);
                    getReleaseResourceController().saveReleaseResource(taxiToRelease);
                } /**
                 * Si choferes son diferentes chofer viejo = ENEABLED, chofer
                 * nuevo = DISABLED
                 */
                else if (null != oldDriver && (null != getDriverId() && !"".equals(getDriverId())) && !oldDriver.getId().equals(getDriverId())) {
                    getReleaseResourceController().saveReleaseResource(oldDriverRR);
                    getReleaseResourceController().updateReleaseResourceDetails(new Person(getDriverId()), null, date, GenericEnumType.DISABLED, getLoggedUser(), date);
                }
            }
        } catch (Exception e) {
            logger.error("releaseResource", e);
        }
    }

    /**
     *
     * @param services
     */
    private void fillTreeTable(List<Service> services) {

        TreeNode node = new DefaultTreeNode(
                new ContractTaxiTreeNodeWrapper(
                        getContract().getName(),
                        getContract().getEndDate(),
                        getContract().getPrice()
                ),
                getRoot()
        );

        services.forEach((Service service) -> {
            TreeNode tn = new DefaultTreeNode(
                    new ContractTaxiTreeNodeWrapper(
                            service.getName(),
                            null,
                            service.getCharge()
                    ),
                    node
            );
        });
    }

    private static final long serialVersionUID = 3878806304110211678L;

    final Logger logger = LogManager.getLogger(TaxiAddBean.class);

    private TaxiController controller;
    private Taxi taxi;
    private String vehicleId;
    private String driverId;
    private String customerId;
    private String colorId;
    private int numberContract = 1;
    private DualListModel<Service> services;
    private TreeNode root;
    private Contract contract;
    private Date startDate;
    private String platform;
    private List<String> platforms;
    private boolean monday;
    private boolean tuesday;
    private boolean wednesday;
    private boolean thursday;
    private boolean friday;
    private boolean saturday;
    private boolean sunday;
    private boolean gps;
    private boolean apc;

    private boolean addTaxiBtnOnclick;
    private boolean addContractsBtnOnclick;
    private boolean addServiceBtnOnclick;

    private ReleaseResourceController releaseResourceController;

    @PostConstruct
    public void init() {
        logger.info("init");

        try {
            loadBundlePropertyFile();
            setTaxi(new Taxi());
            setController(new TaxiController());
            setReleaseResourceController(new ReleaseResourceController());

            List<Service> servicesSource = getController().getAllServices(true);
            List<Service> servicesTarget = new ArrayList<>();

            setServices(new DualListModel<>(servicesSource, servicesTarget));
            setGps(false);
            setApc(false);

            setAddTaxiBtnOnclick(false);
            setRoot(new DefaultTreeNode(new ContractTaxiTreeNodeWrapper(APP, getToday(), Float.NaN), null));
        } catch (Exception e) {
            logger.error("init", e);
        }
    }

    public boolean isApc() {
        return apc;
    }

    public void setApc(boolean apc) {
        this.apc = apc;
    }

    public boolean isGps() {
        return gps;
    }

    public void setGps(boolean gps) {
        this.gps = gps;
    }

    public String getColorId() {
        return colorId;
    }

    public void setColorId(String colorId) {
        this.colorId = colorId;
    }

    public String getDriverId() {
        return driverId;
    }

    public void setDriverId(String driverId) {
        this.driverId = driverId;
    }

    public String getCustomerId() {
        return customerId;
    }

    public void setCustomerId(String customerId) {
        this.customerId = customerId;
    }

    public String getVehicleId() {
        return vehicleId;
    }

    public void setVehicleId(String vehicleId) {
        this.vehicleId = vehicleId;
    }

    public TaxiController getController() {
        return controller;
    }

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

    public Taxi getTaxi() {
        return taxi;
    }

    public void setTaxi(Taxi taxi) {
        this.taxi = taxi;
    }

    public void setAddTaxiBtnOnclick(boolean addTaxiBtnOnclick) {
        this.addTaxiBtnOnclick = addTaxiBtnOnclick;
    }

    public boolean isAddTaxiBtnOnclick() {
        return addTaxiBtnOnclick;
    }

    public List<Vehicle> getVehicles() {
        return getController().fillVehicleComboBox();
    }

    public List<Person> getDrivers() {
        return getController().findAllActiveAndBancaDriversWithoutTaxi(getLoggedUser().getLocation().getId());
    }

    public List<Person> getCustomers() {
        return getController().fillCustomersComboBox();
    }

    public List<Color> getColors() {
        return getController().fillColorsComboBox();
    }

    public DualListModel<Service> getServices() {
        return services;
    }

    public void setServices(DualListModel<Service> services) {
        this.services = services;
    }

    public boolean isAddContractsBtnOnclick() {
        return addContractsBtnOnclick;
    }

    public void setAddContractsBtnOnclick(boolean addContractsBtnOnclick) {
        this.addContractsBtnOnclick = addContractsBtnOnclick;
    }

    public boolean isAddServiceBtnOnclick() {
        return addServiceBtnOnclick;
    }

    public void setAddServiceBtnOnclick(boolean addServiceBtnOnclick) {
        this.addServiceBtnOnclick = addServiceBtnOnclick;
    }

    public TreeNode getRoot() {
        return root;
    }

    public void setRoot(TreeNode root) {
        this.root = root;
    }

    public Contract getContract() {
        return contract;
    }

    public void setContract(Contract contract) {
        this.contract = contract;
    }

    public Date getStartDate() {
        return startDate;
    }

    public void setStartDate(Date startDate) {
        this.startDate = startDate;
    }

    public int getNumberContract() {
        return numberContract;
    }

    public void setNumberContract(int numberContract) {
        this.numberContract = numberContract;
    }

    public String getPlatform() {
        return platform;
    }

    public void setPlatform(String platform) {
        this.platform = platform;
    }

    public List<String> getPlatforms() {
        if (null == platforms) {
            platforms = new ArrayList<>();
            for (PlatformType day : PlatformType.values()) {
                platforms.add(day.toString());
            }
        }
        return platforms;
    }

    public void setPlatforms(List<String> platforms) {
        this.platforms = platforms;
    }

    public boolean isMonday() {
        return monday;
    }

    public void setMonday(boolean monday) {
        this.monday = monday;
    }

    public boolean isTuesday() {
        return tuesday;
    }

    public void setTuesday(boolean tuesday) {
        this.tuesday = tuesday;
    }

    public boolean isWednesday() {
        return wednesday;
    }

    public void setWednesday(boolean wednesday) {
        this.wednesday = wednesday;
    }

    public boolean isThursday() {
        return thursday;
    }

    public void setThursday(boolean thursday) {
        this.thursday = thursday;
    }

    public boolean isFriday() {
        return friday;
    }

    public void setFriday(boolean friday) {
        this.friday = friday;
    }

    public boolean isSaturday() {
        return saturday;
    }

    public void setSaturday(boolean saturday) {
        this.saturday = saturday;
    }

    public boolean isSunday() {
        return sunday;
    }

    public void setSunday(boolean sunday) {
        this.sunday = sunday;
    }

    public ReleaseResourceController getReleaseResourceController() {
        return releaseResourceController;
    }

    public void setReleaseResourceController(ReleaseResourceController releaseResourceController) {
        this.releaseResourceController = releaseResourceController;
    }

}
