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

import com.arrebol.taxiservicios.beans.TaxiGenericBean;
import com.arrebol.taxiservicios.controller.admin.EmployeeController;
import com.arrebol.taxiservicios.controller.catalog.LocationController;
import com.arrebol.taxiservicios.model.admin.Document;
import com.arrebol.taxiservicios.model.catalog.Location;
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.User;
import com.arrebol.taxiservicios.model.enums.AddressType;
import com.arrebol.taxiservicios.model.enums.DocumentType;
import com.arrebol.taxiservicios.model.enums.PaymentType;
import com.arrebol.taxiservicios.model.enums.PersonType;
import com.arrebol.taxiservicios.model.enums.PhoneType;
import com.crov.prase.controller.catalog.DespachoController;
import com.crov.prase.model.catalog.Despacho;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
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.FileUploadEvent;
import org.primefaces.model.UploadedFile;

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

    /**
     * Save/Update an employee in the system.
     */
    public void addEmployee() {
        logger.info("addEmployee");
        try {
            if (!isAddEmployeeBtnOnclick()) {
                getEmployee().setId(UUID.randomUUID().toString());
                getEmployee().setActive(true);
                getEmployee().setRoot(false);
                getEmployee().setCreatedOn(new Date());
                getEmployee().setLocation(getLoggedUser().getLocation());
                // se valida si se está creando un ajustador o un empleado común
                if (getTipoEmpleado().equals("1")) {
                    getEmployee().setAjustador(Boolean.TRUE);
                    getEmployee().setDespacho(getSelectedDespacho() == null || getSelectedDespacho().isEmpty() ? null : new Despacho(getSelectedDespacho()));
                } else {
                    getEmployee().setAjustador(Boolean.FALSE);
                }
            } else {
                if (getTipoEmpleado().equals("1")) {
                    getEmployee().setDespacho(getSelectedDespacho() == null || getSelectedDespacho().isEmpty() ? null : new Despacho(getSelectedDespacho()));
                }
                getEmployee().setLastUpdatedOn(new Date());
            }

            // correccion de fecha 
            if (getEmployee().getBirthdate() != null) {
                getEmployee().setBirthdate(correcciónDeDias(getEmployee().getBirthdate(), 1));
            }
            if (getEmployee().getAdmissionDate() != null) {
                getEmployee().setAdmissionDate(correcciónDeDias(getEmployee().getAdmissionDate(), 1));
            }

            boolean success = getController().addPerson(getEmployee(), getLoggedUser().getUserName(), !isAddEmployeeBtnOnclick());

            if (success) {
                showMessage(FacesMessage.SEVERITY_INFO, ("1".equals(getTipoEmpleado()) ? "Ajustador " : "Empleado ") + (isAddEmployeeBtnOnclick() ? "actualizado " : "agregado "), "El " + ("1".equals(getTipoEmpleado()) ? "Ajustador" : "Empleado") + " fue " + (isAddEmployeeBtnOnclick() ? "actualizado" : "agregado"));
                setAddEmployeeBtnOnclick(true);
            } else {
                logger.error("Person " + getEmployee() + " was not " + (isAddEmployeeBtnOnclick() ? "updated" : "saved"));
                showMessage(FacesMessage.SEVERITY_ERROR, "Error", "Ocurrio un error al " + (isAddEmployeeBtnOnclick() ? "actualizar" : "agregar") + " el " + ("1".equals(getTipoEmpleado()) ? "ajustador" : "empleado"));
            }
        } catch (Exception e) {
            logger.error("addEmployee: " + e);
            showMessage(FacesMessage.SEVERITY_FATAL, "", "");
        }
    }

    /**
     * Add RFC, Email, CURP, and Local/Mobile phones to employee.
     */
    public void addContactDetails() {
        logger.info("addContactDetails");
        try {

            if (!isAddContactBtnOnclick()) {
                getContactNumbers().stream().map((contactNumber) -> {
                    contactNumber.setId(UUID.randomUUID().toString());
                    return contactNumber;
                }).forEachOrdered((contactNumber) -> {
                    contactNumber.setPerson(getEmployee());
                    contactNumber.setCreatedOn(new Date());
                });
            } else {
                getContactNumbers().forEach((phone) -> {
                    phone.setLastUpdatedOn(new Date());
                });
            }

            getEmployee().setLastUpdatedOn(new Date());

            boolean success = getController().saveOrUpdatePersonContactDetailsById(
                    getEmployee().getId(), getEmployee().getCurp(),
                    getEmployee().getRfc(), getEmployee().getMail(),
                    getContactNumbers(), getLoggedUser().getUserName(),
                    !isAddContactBtnOnclick(), !isAddContactBtnOnclick());

            if (success) {
                setAddContactBtnOnclick(true);
                logger.info("Contact detais saved.");
                showMessage(FacesMessage.SEVERITY_INFO, getBundlePropertyFile().getString("person.add.contact.title"), getBundlePropertyFile().getString("person.add.contact.success.desc"));
            } else {
                logger.error("Contact details can not be saved.");
                logger.error("Contact details: " + getEmployee());
                logger.error("Numbers details: " + getContactNumbers());
                showMessage(FacesMessage.SEVERITY_ERROR, getBundlePropertyFile().getString("person.add.contact.title"), getBundlePropertyFile().getString("person.add.contact.fail.desc"));
            }
        } catch (Exception e) {
            logger.error("addContactDetails: " + e);
            showMessage(FacesMessage.SEVERITY_FATAL, getBundlePropertyFile().getString("person.add.contact.title"), getBundlePropertyFile().getString("person.add.contact.exception.desc"));
        }
    }

    /**
     * Save new employee details.
     */
    public void addAddress() {
        logger.info("addAddress");
        try {
            /*
            getAddress().setStreet(facesContext().getExternalContext().getRequestParameterMap().get("addAddressForm:streetHdn"));
            getAddress().setExtendedAddress(facesContext().getExternalContext().getRequestParameterMap().get("addAddressForm:colonyHdn"));
            getAddress().setLocality(facesContext().getExternalContext().getRequestParameterMap().get("addAddressForm:departmentHdn"));
            getAddress().setRegion(facesContext().getExternalContext().getRequestParameterMap().get("addAddressForm:stateHdn"));
            getAddress().setZipCode(facesContext().getExternalContext().getRequestParameterMap().get("addAddressForm:cpHdn"));
             */
            if (!isAddAddressBtnOnclick()) {
                getAddress().setId(UUID.randomUUID().toString());
                getAddress().setCreatedOn(new Date());
            } else {
                getAddress().setLastUpdatedOn(new Date());
            }

            boolean success = getController().saveOrUpdateAddress(getAddress(), !isAddAddressBtnOnclick(), getEmployee().getId(), getLoggedUser().getUserName());

            if (success) {
                setAddAddressBtnOnclick(true);
                logger.info("Address detais saved.");
                showMessage(FacesMessage.SEVERITY_INFO, getBundlePropertyFile().getString("person.add.address.title"), getBundlePropertyFile().getString("person.add.address.success.desc"));
            } else {
                logger.error("Address details not saved " + getAddress());
                showMessage(FacesMessage.SEVERITY_ERROR, getBundlePropertyFile().getString("person.add.address.title"), getBundlePropertyFile().getString("person.add.address.fail.desc"));
            }

        } catch (Exception e) {
            logger.error("addAddress: " + e);
            showMessage(FacesMessage.SEVERITY_FATAL, getBundlePropertyFile().getString("person.add.address.title"), getBundlePropertyFile().getString("person.add.address.exception.desc"));
        }
    }

    /**
     * Update payment details from employee.
     */
    public void addPayment() {
        logger.info("addPayment");
        try {
            getEmployee().setPaymentType(getPaymentType());
            getEmployee().setLastUpdatedOn(new Date());
            boolean success = getController().addPayment(getEmployee(), getLoggedUser().getUserName());

            if (success) {
                setAddPaymentBtnOnclick(true);
                logger.info("Payment details saved.");
                showMessage(FacesMessage.SEVERITY_INFO, getBundlePropertyFile().getString("employee.add.payment.title"), getBundlePropertyFile().getString("employee.add.payment.success.desc"));
            } else {
                logger.error("Payment detais not saved " + address);
                showMessage(FacesMessage.SEVERITY_ERROR, getBundlePropertyFile().getString("employee.add.payment.title"), getBundlePropertyFile().getString("employee.add.payment.fail.desc"));
            }
        } catch (Exception e) {
            logger.error("addPayment: " + e);

            showMessage(FacesMessage.SEVERITY_FATAL, getBundlePropertyFile().getString("employee.add.payment.title"), getBundlePropertyFile().getString("employee.add.payment.exception.desc"));
        }
    }

    public void handleFileUpload(FileUploadEvent event) {
        logger.info("handleFileUpload.");
        try {
            UploadedFile file = event.getFile();

            List<Document> documents = new ArrayList<Document>();

            getDocument().setPath(file.getContentType());
            getDocument().setFileName(file.getFileName());
            getDocument().setContent(file.getContents());

            if (!isAddPhotoEmployeeBtnOnclick()) {
                getDocument().setId(UUID.randomUUID().toString());
                getDocument().setPerson(new Person(getEmployee().getId()));
                getDocument().setCreatedBy(new User(getLoggedUser().getId(), ""));
            } else {
                getDocument().setLastUpdatedBy(new User(getLoggedUser().getId(), ""));
            }

            documents.add(getDocument());

            boolean success = getController().saveOrUpdatePhotos(documents, !isAddPhotoEmployeeBtnOnclick());

            if (success) {
                setAddPhotoEmployeeBtnOnclick(true);
                setPhotoName(getBundlePropertyFile().getString("document.title") + " " + file.getFileName() + " " + getBundlePropertyFile().getString("driver.document.add.success.desc"));

                logger.info("Employee photo saved.");
                showMessage(FacesMessage.SEVERITY_INFO, getBundlePropertyFile().getString("person.add.photo.title"), getBundlePropertyFile().getString("person.add.photo.success.desc"));
            } else {
                setPhotoName(getBundlePropertyFile().getString("document.title") + " " + file.getFileName() + " " + getBundlePropertyFile().getString("driver.document.add.fail.desc"));

                logger.error("Employee photo not saved " + getDocument());
                showMessage(FacesMessage.SEVERITY_ERROR, getBundlePropertyFile().getString("person.add.photo.title"), getBundlePropertyFile().getString("person.add.photo.fail.desc"));
            }
        } catch (Exception e) {
            logger.error("handleFileUpload: " + e);

            setPhotoName(getBundlePropertyFile().getString("document.exception.desc"));
            showMessage(FacesMessage.SEVERITY_FATAL, getBundlePropertyFile().getString("person.add.photo.title"), getBundlePropertyFile().getString("person.add.photo.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 = 9195597038948525188L;

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

    private EmployeeController controller;
    private LocationController locationController;
    private DespachoController despachoController;
    private List<Despacho> listDespacho;
    private String selectedDespacho;
    private String locationId;
    private List<Location> locations;
    private Person employee;
    private List<ContactNumber> contactNumbers;
    private Address address;
    private List<PaymentType> paymentTypes;
    private PaymentType paymentType;
    private Document document;
    private String photoName;
    private String tipoEmpleado;

    private boolean addEmployeeBtnOnclick;
    private boolean addContactBtnOnclick;
    private boolean addAddressBtnOnclick;
    private boolean addPaymentBtnOnclick;
    private boolean addPhotoEmployeeBtnOnclick;
    private Date sixteenYearsOld;

    @PostConstruct
    public void init() {
        logger.info("init");
        try {
            Calendar calendar = Calendar.getInstance();

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

            loadBundlePropertyFile();

            setController(new EmployeeController());
            setLocationController(new LocationController());
            setDespachoController(new DespachoController());

            setLocations(getLocationController().fillLocationDatatable());
            setEmployee(new Person(PersonType.EMPLOYEE));
            setAddress(new Address(AddressType.HOME));
            setDocument(new Document(DocumentType.SELFIE));

            getContactNumbers().add(new ContactNumber(PhoneType.HOME));
            getContactNumbers().add(new ContactNumber(PhoneType.MOBILE));

            setAddEmployeeBtnOnclick(false);
            setAddContactBtnOnclick(false);
            setAddAddressBtnOnclick(false);
            setAddPaymentBtnOnclick(false);
            setAddPhotoEmployeeBtnOnclick(false);

            setTipoEmpleado(externalContext().getRequestParameterMap().get("tipoEmpleado"));
            if (getTipoEmpleado().equals("1")) {
                logger.info("Ajustador");
                setTipoEmpleado("1");
                setListDespacho(getDespachoController().fillDespachoByLocation(getLoggedUser().getLocation()));
            } else {
                logger.info("Empleado");
                setTipoEmpleado("0");
            }

            getPaymentTypes().addAll(Arrays.asList(PaymentType.values()));
        } catch (Exception e) {
            logger.error("init", e);
        }
    }

    public LocationController getLocationController() {
        return locationController;
    }

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

    public String getLocationId() {
        return locationId;
    }

    public void setLocationId(String locationId) {
        this.locationId = locationId;
    }

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

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

    public EmployeeController getController() {
        return controller;
    }

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

    public Person getEmployee() {
        return employee;
    }

    public void setEmployee(Person employee) {
        this.employee = employee;
    }

    public List<ContactNumber> getContactNumbers() {
        if (null == contactNumbers) {
            contactNumbers = new ArrayList<ContactNumber>();
        }
        return contactNumbers;
    }

    public Address getAddress() {
        return address;
    }

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

    public List<PaymentType> getPaymentTypes() {
        if (null == paymentTypes) {
            paymentTypes = new ArrayList<PaymentType>();
        }
        return paymentTypes;
    }

    public void setPaymentTypes(List<PaymentType> paymentTypes) {
        this.paymentTypes = paymentTypes;
    }

    public void setAddEmployeeBtnOnclick(boolean addEmployeeBtnOnclick) {
        this.addEmployeeBtnOnclick = addEmployeeBtnOnclick;
    }

    public Document getDocument() {
        return document;
    }

    public void setDocument(Document document) {
        this.document = document;
    }

    public String getPhotoName() {
        return photoName;
    }

    public void setPhotoName(String photoName) {
        this.photoName = photoName;
    }

    public boolean isAddEmployeeBtnOnclick() {
        return addEmployeeBtnOnclick;
    }

    public boolean isAddContactBtnOnclick() {
        return addContactBtnOnclick;
    }

    public void setAddContactBtnOnclick(boolean addContactBtnOnclick) {
        this.addContactBtnOnclick = addContactBtnOnclick;
    }

    public boolean isAddAddressBtnOnclick() {
        return addAddressBtnOnclick;
    }

    public void setAddAddressBtnOnclick(boolean addAddressBtnOnclick) {
        this.addAddressBtnOnclick = addAddressBtnOnclick;
    }

    public boolean isAddPaymentBtnOnclick() {
        return addPaymentBtnOnclick;
    }

    public void setAddPaymentBtnOnclick(boolean addPaymentBtnOnclick) {
        this.addPaymentBtnOnclick = addPaymentBtnOnclick;
    }

    public boolean isAddPhotoEmployeeBtnOnclick() {
        return addPhotoEmployeeBtnOnclick;
    }

    public void setAddPhotoEmployeeBtnOnclick(boolean addPhotoEmployeeBtnOnclick) {
        this.addPhotoEmployeeBtnOnclick = addPhotoEmployeeBtnOnclick;
    }

    public Date getSixteenYearsOld() {
        return sixteenYearsOld;
    }

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

    public PaymentType getPaymentType() {
        return paymentType;
    }

    public void setPaymentType(PaymentType paymentType) {
        this.paymentType = paymentType;
    }

    public String getTipoEmpleado() {
        return tipoEmpleado;
    }

    public void setTipoEmpleado(String tipoEmpleado) {
        this.tipoEmpleado = tipoEmpleado;
    }

    public DespachoController getDespachoController() {
        return despachoController;
    }

    public void setDespachoController(DespachoController despachoController) {
        this.despachoController = despachoController;
    }

    public List<Despacho> getListDespacho() {
        return listDespacho;
    }

    public void setListDespacho(List<Despacho> listDespacho) {
        this.listDespacho = listDespacho;
    }

    public String getSelectedDespacho() {
        return selectedDespacho;
    }

    public void setSelectedDespacho(String selectedDespacho) {
        this.selectedDespacho = selectedDespacho;
    }

}
