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

import com.arrebol.taxiservicios.beans.TaxiGenericBean;
import com.arrebol.taxiservicios.controller.admin.CustomerController;
import com.arrebol.taxiservicios.controller.admin.TaxiController;
import com.arrebol.taxiservicios.controller.catalog.LocationController;
import com.arrebol.taxiservicios.controller.catalog.RegimenFiscalController;
import com.arrebol.taxiservicios.model.admin.PersonHasService;
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.Location;
import com.arrebol.taxiservicios.model.catalog.RegimenFiscal;
import com.arrebol.taxiservicios.model.catalog.Vehicle;
import com.arrebol.taxiservicios.model.core.Address;
import com.arrebol.taxiservicios.model.core.ContactNumber;
import com.arrebol.taxiservicios.model.core.Person;
import com.arrebol.taxiservicios.model.core.PersonCommercialInvoice;
import com.arrebol.taxiservicios.model.enums.AddressType;
import com.arrebol.taxiservicios.model.enums.BasicType;
import com.arrebol.taxiservicios.model.enums.PhoneType;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Set;
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.DualListModel;
import org.primefaces.model.TreeNode;

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

    /**
     * Save/Update an vehicle in the system.
     */
    public void addVehicle() {
        try {
            logger.info("addVehicle");
            getTaxiAdd().setActive(true);
            getTaxiAdd().setLocation(getLoggedUser().getLocation());
            getTaxiAdd().setCustomer(new Person(getCustomerId()));
            getTaxiAdd().setVehicle(new Vehicle(getVehicleId()));
            getTaxiAdd().setGps(BasicType.DISABLED);
            getTaxiAdd().setApc(BasicType.DISABLED);
            getTaxiAdd().setEconomicNumber("");
            boolean success = getController().addVehiculo(getTaxiAdd(), getLoggedUser());
            if (success) {
                setTaxi(getControllerTaxi().findAllTaxisByCustomer(getCustomerId()));
                newVehiculos();
                showMessage(FacesMessage.SEVERITY_INFO, getBundlePropertyFile().getString("taxi.add.title"), getBundlePropertyFile().getString("taxi.add.success.desc"));
            } else {
                logger.error("Taxi " + getTaxiAdd() + " was not saved");
                showMessage(FacesMessage.SEVERITY_ERROR, getBundlePropertyFile().getString("taxi.add.title"), getBundlePropertyFile().getString("taxi.add.fail.desc"));
            }
        } catch (Exception e) {
            logger.error("Ocurrió un error al agregar el taxi");
            showMessage(FacesMessage.SEVERITY_FATAL, getBundlePropertyFile().getString("taxi.add.title"), getBundlePropertyFile().getString("taxi.add.fail.desc"));
        }
    }

    public void editarVehicle() {
        try {
            logger.info("addVehicle");
            getTaxiAdd().setVehicle(new Vehicle(getVehicleId()));
            boolean success = getController().updateVehiculo(getTaxiAdd(), getLoggedUser());
            if (success) {
                setTaxi(getControllerTaxi().findAllTaxisByCustomer(getCustomerId()));
                newVehiculos();
                showMessage(FacesMessage.SEVERITY_INFO, "Actualización realizada", "Los datos del vehículo se actualizaron correctamente");
            } else {
                logger.error("Taxi " + getTaxiAdd() + " was not saved");
                showMessage(FacesMessage.SEVERITY_ERROR, "Error", "Ocurrió un error al actualizar el taxi");
            }
        } catch (Exception e) {
            logger.error("Ocurrió un error al agregar el taxi");
            showMessage(FacesMessage.SEVERITY_FATAL, "Error", "Ocurrió un error al actualizar el taxi");
        }
    }

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

            // correccion de fecha 
            getCustomer().setBirthdate(correcciónDeDias(getCustomer().getBirthdate(), 1));

            boolean success = getController().updatePersonCustomerById(
                    getCustomer().getFirstName(), getCustomer().getSecondName(),
                    getCustomer().getLastName(), getCustomer().getMiddleName(),
                    getCustomer().getBirthdate(), getCustomer().getId(),
                    getLoggedUser().getId(), getCustomer().getPayment(), 0F, getLoggedUser().getLocation().getId());

            if (success) {
                showMessage(FacesMessage.SEVERITY_INFO,
                        getBundlePropertyFile().getString("customer.edit.title"),
                        getBundlePropertyFile().getString("customer.edit.success.desc"));
            } else {
                logger.error("Customer " + getCustomer() + " was not updated");
                showMessage(FacesMessage.SEVERITY_ERROR,
                        getBundlePropertyFile().getString("customer.edit.title"),
                        getBundlePropertyFile().getString("customer.edit.fail.desc"));
            }
        } catch (Exception e) {
            logger.error("updateCustomer: " + e);
            showMessage(FacesMessage.SEVERITY_FATAL,
                    getBundlePropertyFile().getString("customer.edit.title"),
                    getBundlePropertyFile().getString("customer.edit.exception.desc"));
        }
    }

    public void addCommercialInvoice() {

        boolean success = getController().saveOrUpdatePersonCommercialInvoice(getCustomerCommercialInvoice(), getLoggedUser().getId(), getRegimenFiscalId());

        if (success) {

            logger.info("Address detais saved.");
            showMessage(FacesMessage.SEVERITY_INFO, "Alta de información para facturar", "Se agrego la informacion para facturar");

        } else {
            logger.error("Address details not saved " + getAddress());
            showMessage(FacesMessage.SEVERITY_ERROR, "Alta de información para facturar", "No se pudo agregar la informacion para facturar");
        }
    }

    public void editContactDetails() {
        logger.info("editContactDetails");
        try {
            boolean success = getController().saveOrUpdateCustomerContactDetailsById(
                    getCustomerId(), getCustomer().getCurp(),
                    getCustomer().getRfc(), getCustomer().getMail(),
                    getContactNumbers(), getLoggedUser().getUserName(), isSaveLocalNumber(), isSaveMobile());

            if (success) {
                setSaveLocalNumber(false);
                setSaveMobile(false);
                showMessage(FacesMessage.SEVERITY_INFO,
                        getBundlePropertyFile().getString("person.edit.contact.details.title"),
                        getBundlePropertyFile().getString("person.edit.contact.details.success.desc"));
            } else {
                logger.error("Employee " + getCustomer() + " was not updated");
                showMessage(FacesMessage.SEVERITY_ERROR,
                        getBundlePropertyFile().getString("person.edit.contact.details.title"),
                        getBundlePropertyFile().getString("person.edit.contact.details.fail.desc"));
            }
        } catch (Exception e) {
            logger.error("editContactDetails: " + e);
            showMessage(FacesMessage.SEVERITY_FATAL,
                    getBundlePropertyFile().getString("person.edit.contact.details.title"),
                    getBundlePropertyFile().getString("person.edit.contact.details.exception.desc"));
        }
    }

    public void editAddress(String formName) {
        logger.info("editContactDetails");
        try {
            /*
            getAddress().setStreet(facesContext().getExternalContext().getRequestParameterMap().get(formName + ":streetHdn"));
            getAddress().setExtendedAddress(facesContext().getExternalContext().getRequestParameterMap().get(formName + ":colonyHdn"));
            getAddress().setLocality(facesContext().getExternalContext().getRequestParameterMap().get(formName + ":departmentHdn"));
            getAddress().setRegion(facesContext().getExternalContext().getRequestParameterMap().get(formName + ":stateHdn"));
            getAddress().setZipCode(facesContext().getExternalContext().getRequestParameterMap().get(formName + ":cpHdn"));
             */
            boolean success;
            if (isSaveAddress()) {
                success = getController().saveOrUpdateAddress(getAddress(),
                        isSaveAddress(), getCustomerId(), getLoggedUser().getUserName());
            } else {
                success = getController().updateAddress(address, getLoggedUser(), new Date());

            }

            if (success) {
                setSaveAddress(false);
                showMessage(FacesMessage.SEVERITY_INFO,
                        getBundlePropertyFile().getString("person.edit.address.title"),
                        getBundlePropertyFile().getString("person.edit.address.success.desc"));
            } else {
                logger.error("Customer " + getCustomer() + " was not updated");
                showMessage(FacesMessage.SEVERITY_ERROR,
                        getBundlePropertyFile().getString("person.edit.address.title"),
                        getBundlePropertyFile().getString("person.edit.address.fail.desc"));
            }
        } catch (Exception e) {
            logger.error("editContactDetails: " + e);
            showMessage(FacesMessage.SEVERITY_FATAL,
                    getBundlePropertyFile().getString("person.edit.address.title"),
                    getBundlePropertyFile().getString("person.edit.address.exception.desc"));
        }
    }

    /**
     * Save or update the services into a customer.
     */
    public void saveOrUpdatePersonHasServices() {
        logger.info("saveOrUpdateServices");
        try {
            boolean success = getController().saveOrUpdatePersonHasServices(
                    getCustomer().getId(), getServices().getTarget(), getServices().getSource());

            if (success) {
                logger.info("Services by Customer saved.");
                showMessage(FacesMessage.SEVERITY_INFO,
                        getBundlePropertyFile().getString("customer.service.update.title"),
                        getBundlePropertyFile().getString("customer.service.update.success.desc"));
            } else {
                logger.error("Services by customer didn't save.");
                showMessage(FacesMessage.SEVERITY_ERROR,
                        getBundlePropertyFile().getString("customer.service.update.title"),
                        getBundlePropertyFile().getString("customer.service.update.fail.desc"));
            }
        } catch (Exception e) {
            logger.error("saveOrUpdateServices: " + e);

            showMessage(FacesMessage.SEVERITY_FATAL,
                    getBundlePropertyFile().getString("customer.service.update.title"),
                    getBundlePropertyFile().getString("customer.service.update.exception.desc"));
        }
    }

    private Date correcciónDeDias(Date fecha, int dias) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(fecha);
        calendar.add(Calendar.DAY_OF_YEAR, dias);
        return calendar.getTime();
    }

    private static final long serialVersionUID = -4201218847905362380L;

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

    private CustomerController controller;
    private String customerId;
    private Person customer;
    private PersonCommercialInvoice customerCommercialInvoice;
    private List<ContactNumber> contactNumbers;
    private Address address;
    private Date sixteenYearsOld;

    private List<Taxi> taxi;
    TaxiController controllerTaxi;
    private Taxi selectedTaxi;
    private Taxi taxiAdd;
    private String vehicleId;
    private String colorId;

    private DualListModel<Service> services;
    private TreeNode wrapers;
    private boolean saveMobile;
    private boolean saveLocalNumber;
    private boolean saveAddress;

    private LocationController locationController;
    private RegimenFiscalController regimenFiscalController;
    private String regimenFiscalId;
    private List<Location> locations;
    private List<RegimenFiscal> regimenFiscal;
    private ContactNumber phoneHome;
    private ContactNumber mobileHome;

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

            Calendar calendar = Calendar.getInstance();

            calendar.add(Calendar.YEAR, -15);

            setSixteenYearsOld(calendar.getTime());
            setController(new CustomerController());
            setControllerTaxi(new TaxiController());

            setLocationController(new LocationController());
            setRegimenFiscalController(new RegimenFiscalController());
            setLocations(getLocationController().fillLocationDatatable());
            setCustomerId(externalContext().getRequestParameterMap().get("customerForm:customerDtTbl_selection"));
            setCustomer(getController().getPersonById(getCustomerId()));
            setCustomerCommercialInvoice(getController().getPersonCommercialInvoiceById(getCustomerId()));

            setTaxi(getControllerTaxi().findAllTaxisByCustomer(getCustomerId()));
            if (getCustomerCommercialInvoice() == null) {
                setCustomerCommercialInvoice(new PersonCommercialInvoice());
                getCustomerCommercialInvoice().setIdPerson(getCustomerId());

            }

            setRegimenFiscal(getRegimenFiscalController().fillRegimenFiscalDatatable());
            setRegimenFiscalId(getCustomerCommercialInvoice().getRegimenFiscal() != null ? getCustomerCommercialInvoice().getRegimenFiscal().getId() : null);
            //setContactNumbers(getController().getContactNumberByIdPerson(customer));
            setPhoneHome(getController().getContacNumberByIdPersonPhoneType(customer, PhoneType.HOME));
            setMobileHome(getController().getContacNumberCustomerByIdPersonPhoneType(customer, PhoneType.MOBILE));
            setAddress(getController().getAddressCustomerByIdPerson2(customer));

            if (null != getAddress()) {
                setSaveAddress(false);

            } else {
                setSaveAddress(true);
                setAddress(new Address(UUID.randomUUID().toString(), AddressType.HOME));
            }

            setContactNumbers(new ArrayList<ContactNumber>());
            if (null != getPhoneHome()) {

                getContactNumbers().add(getPhoneHome());

            } else {
                getContactNumbers().add(
                        null == phoneHome
                                ? new ContactNumber(UUID.randomUUID().toString(), PhoneType.HOME)
                                : phoneHome);
            }

            if (null != getMobileHome()) {

                getContactNumbers().add(getMobileHome());

            } else {
                getContactNumbers().add(
                        null == mobileHome
                                ? new ContactNumber(UUID.randomUUID().toString(), PhoneType.MOBILE)
                                : mobileHome);
            }

            setSaveLocalNumber(null == phoneHome);
            setSaveMobile(null == mobileHome);

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

            personHasServices.forEach((personService) -> {
                Service service = new Service(personService.getId().getServiceId());

                if (servicesSource.contains(service)) {
                    int index = servicesSource.indexOf(service);

                    servicesTarget.add(servicesSource.get(index));
                    servicesSource.remove(service);
                }
            });

            setServices(new DualListModel<Service>(servicesSource, servicesTarget));
        } catch (Exception e) {
            logger.info("init", e);
        }
    }

    public void cargarVehiculo() {
        setTaxiAdd(getSelectedTaxi());
        setVehicleId(getSelectedTaxi().getVehicle().getId());
    }

    public void newVehiculos() {
        setTaxiAdd(new Taxi());
        setVehicleId(null);
    }

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

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

    public List<Taxi> getTaxi() {
        return taxi;
    }

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

    public TaxiController getControllerTaxi() {
        return controllerTaxi;
    }

    public void setControllerTaxi(TaxiController controllerTaxi) {
        this.controllerTaxi = controllerTaxi;
    }

    public Taxi getSelectedTaxi() {
        return selectedTaxi;
    }

    public void setSelectedTaxi(Taxi selectedTaxi) {
        this.selectedTaxi = selectedTaxi;
    }

    public Taxi getTaxiAdd() {
        return taxiAdd;
    }

    public void setTaxiAdd(Taxi taxiAdd) {
        this.taxiAdd = taxiAdd;
    }

    public String getVehicleId() {
        return vehicleId;
    }

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

    public String getColorId() {
        return colorId;
    }

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

    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 CustomerController getController() {
        return controller;
    }

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

    public String getCustomerId() {
        return customerId;
    }

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

    public Person getCustomer() {
        return customer;
    }

    public void setCustomer(Person customer) {
        this.customer = customer;
    }

    public List<ContactNumber> getContactNumbers() {
        return contactNumbers;
    }

    public void setContactNumbers(List<ContactNumber> contactNumbers) {
        this.contactNumbers = contactNumbers;
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    public Date getSixteenYearsOld() {
        return sixteenYearsOld;
    }

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

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

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

    public void setWrapers(TreeNode wrapers) {
        this.wrapers = wrapers;
    }

    public boolean isSaveMobile() {
        return saveMobile;
    }

    public void setSaveMobile(boolean saveMobile) {
        this.saveMobile = saveMobile;
    }

    public boolean isSaveLocalNumber() {
        return saveLocalNumber;
    }

    public void setSaveLocalNumber(boolean saveLocalNumber) {
        this.saveLocalNumber = saveLocalNumber;
    }

    public boolean isSaveAddress() {
        return saveAddress;
    }

    public void setSaveAddress(boolean saveAddress) {
        this.saveAddress = saveAddress;
    }

    public ContactNumber getPhoneHome() {
        return phoneHome;
    }

    public void setPhoneHome(ContactNumber phoneHome) {
        this.phoneHome = phoneHome;
    }

    public ContactNumber getMobileHome() {
        return mobileHome;
    }

    public void setMobileHome(ContactNumber mobileHome) {
        this.mobileHome = mobileHome;
    }

    public RegimenFiscalController getRegimenFiscalController() {
        return regimenFiscalController;
    }

    public void setRegimenFiscalController(RegimenFiscalController regimenFiscalController) {
        this.regimenFiscalController = regimenFiscalController;
    }

    public String getRegimenFiscalId() {
        return regimenFiscalId;
    }

    public void setRegimenFiscalId(String regimenFiscalId) {
        this.regimenFiscalId = regimenFiscalId;
    }

    public List<RegimenFiscal> getRegimenFiscal() {
        return regimenFiscal;
    }

    public void setRegimenFiscal(List<RegimenFiscal> regimenFiscal) {
        this.regimenFiscal = regimenFiscal;
    }

    public PersonCommercialInvoice getCustomerCommercialInvoice() {

        return customerCommercialInvoice;
    }

    public void setCustomerCommercialInvoice(PersonCommercialInvoice customerCommercialInvoice) {
        this.customerCommercialInvoice = customerCommercialInvoice;
    }

}
