package com.arrebol.taxiservicios.beans.admin.driver;

import com.arrebol.taxiservicios.beans.TaxiGenericBean;
import com.arrebol.taxiservicios.controller.admin.DriverController;
import com.arrebol.taxiservicios.controller.catalog.LocationController;
import com.arrebol.taxiservicios.model.admin.Document;
import com.arrebol.taxiservicios.model.admin.Reference;
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.BasicType;
import com.arrebol.taxiservicios.model.enums.DocumentType;
import com.arrebol.taxiservicios.model.enums.PhoneType;
import com.arrebol.taxiservicios.model.enums.ReferenceType;
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.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.event.FileUploadEvent;
import org.primefaces.model.UploadedFile;

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

    /**
     *
     */
    public void updateDriver() {
        logger.info("updateDriver");
        
        if(juridico)
        {
           getDriver().setJuridico(BasicType.ENEBLED); 
        }
        else
        {
           getDriver().setJuridico(BasicType.DISABLED); 
        }
        
        try {
            boolean success = getController().updatePersonById(
                    getDriver().getFirstName(), getDriver().getSecondName(),
                    getDriver().getLastName(), getDriver().getMiddleName(),
                    getDriver().getBirthdate(), getDriver().getAdmissionDate(),
                    getDriver().getId(), getLoggedUser().getUserName(), getDriver().getAdeudo(), locationId, getDriver().getJuridico());

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

    public void editContactDetails() {
        logger.info("editContactDetails");
        try {
            boolean success = getController().saveOrUpdatePersonContactDetailsById(
                    getDriverId(), getDriver().getCurp(),
                    getDriver().getRfc(), getDriver().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 " + getDriver() + " 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"));
        }
    }

    /**
     *
     * @param formName
     */
    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 = getController().saveOrUpdateAddress(getAddress(),
                    isSaveAddress(), getDriverId(), getLoggedUser().getUserName());

            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 " + getDriver() + " 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"));
        }
    }

    public void updateDriverCard() {
        logger.info("updateDriverCard");
        try {
            boolean success = getController().updateDriverCardDetails(
                    getDriver().getIfe(), getDriver().getLicense(),
                    getDriver().getExpirationLicenseDate(),
                    getDriver().getId(), getLoggedUser().getId());

            if (success) {
                logger.info("Driver card detais updated.");
                showMessage(FacesMessage.SEVERITY_INFO,
                        getBundlePropertyFile().getString("driver.card.title"),
                        getBundlePropertyFile().getString("driver.update.card.success.desc"));
            } else {
                logger.error("Driver card details not updated");
                showMessage(FacesMessage.SEVERITY_ERROR,
                        getBundlePropertyFile().getString("driver.card.title"),
                        getBundlePropertyFile().getString("driver.update.card.fail.desc"));
            }

        } catch (Exception e) {
            logger.error("updateDriverCard: " + e);

            showMessage(FacesMessage.SEVERITY_FATAL,
                    getBundlePropertyFile().getString("driver.card.title"),
                    getBundlePropertyFile().getString("driver.update.card.exception.desc"));
        }
    }
    
    public void updateDriverAval() {
        logger.info("updateDriverAval");
        try {
            boolean success = getController().updateDriverAvalDetails(
                    getDriver().getNameEndorsement(), getDriver().getParentescoEndorsement(),
                    getDriver().getPhoneEndorsement(),
                    getDriver().getId(), getLoggedUser().getId());

            if (success) {
                logger.info("Driver aval detais saved.");
                showMessage(FacesMessage.SEVERITY_INFO,
                        getBundlePropertyFile().getString("driver.card.title"),
                        getBundlePropertyFile().getString("driver.update.card.success.desc"));
            } else {
                logger.error("Driver aval details not saved");
                showMessage(FacesMessage.SEVERITY_ERROR,
                        getBundlePropertyFile().getString("driver.card.title"),
                        getBundlePropertyFile().getString("driver.update.card.fail.desc"));
            }
        } catch (Exception e) {
            logger.error("updateDriverAval: " + e);

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

    /**
     * Update personal references from taxi driver
     */
    public void updateReferences() {
        logger.info("addReferences");
        try {
            if (isSaveReferenceFirstTime()) {
                getReferences().stream().map((Reference ref) -> {
                    ref.setId(UUID.randomUUID().toString());
                    return ref;
                }).forEachOrdered((Reference ref) -> {
                    ref.setPerson(new Person(getDriver().getId()));
                    ref.setCreatedBy(new User(getLoggedUser().getId(), ""));
                });
            } else {
                getReferences().forEach((Reference ref) -> {
                    ref.setLastUpdatedBy(new User(getLoggedUser().getId(), ""));
                });
            }

            boolean success = getController().saveOrUpdateReference(
                    getReferences(), isSaveReferenceFirstTime());

            if (success) {
                setSaveReferenceFirstTime(false);
                logger.info("Driver card references saved.");
                showMessage(FacesMessage.SEVERITY_INFO,
                        getBundlePropertyFile().getString("driver.card.title"),
                        getBundlePropertyFile().getString("driver.update.card.success.desc"));
            } else {
                logger.error("Driver card references not saved");
                showMessage(FacesMessage.SEVERITY_ERROR,
                        getBundlePropertyFile().getString("driver.card.title"),
                        getBundlePropertyFile().getString("driver.update.card.fail.desc"));
            }
        } catch (Exception e) {
            logger.error("addReferences: " + e);

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

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

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

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

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

            documents.add(getDocument());

            boolean success = getController().saveOrUpdatePhotos(documents, isSavePhotoBtnOnclick());

            if (success) {
                setSavePhotoBtnOnclick(false);
                setPhotoName(getBundlePropertyFile().getString("document.title")
                        + " " + file.getFileName()
                        + " " + getBundlePropertyFile().getString("driver.document.update.success.desc"));

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

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

            setPhotoName(getBundlePropertyFile().getString("document.exception.desc"));
            showMessage(FacesMessage.SEVERITY_FATAL,
                    getBundlePropertyFile().getString("person.edit.photo.title"),
                    getBundlePropertyFile().getString("person.edit.photo.exception.desc"));
        }
    }

    private static final long serialVersionUID = 3955275999317417237L;

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

    private DriverController controller;
    private String driverId;
    private Person driver;
    private List<ContactNumber> contactNumbers;
    private Address address;
    private Date sixteenYearsOld;
    private boolean saveMobile;
    private boolean saveLocalNumber;
    private boolean saveAddress;
    private Date today;
    private List<Reference> references;
    private List<ReferenceType> referenceTypes;
    private boolean saveReferenceFirstTime;
    private Document document;
    private String photoName;
    private boolean savePhotoBtnOnclick;
    private LocationController locationController;
    private String locationId;
    private List<Location> locations;
    private boolean juridico;

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

            Calendar calendar = Calendar.getInstance();

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

            setSixteenYearsOld(calendar.getTime());
            setController(new DriverController());
            setLocationController(new LocationController());
            setLocations(getLocationController().fillLocationDatatable());
            setDriverId(externalContext().getRequestParameterMap().get("driverForm:driverDtTbl_selection"));
            setDriver(getController().getPersonById(getDriverId()));
            setLocationId(getDriver().getLocation().getId());
            setContactNumbers(new ArrayList<>());
            
            if(getDriver().getJuridico()== BasicType.ENEBLED)
            {
                juridico = true;
            }
            else
            {
                juridico = false;
            }

            if (null != getDriver().getAddresses() && !getDriver().getAddresses().isEmpty()) {
                ((Set<Address>) getDriver().getAddresses())
                        .forEach((addrss) -> {
                            switch (addrss.getAddressType()) {
                                case HOME:
                                    setSaveAddress(false);
                                    setAddress(addrss);
                                    break;
                            }
                        });
            } else {
                setSaveAddress(true);
                setAddress(new Address(UUID.randomUUID().toString(), AddressType.HOME));
            }

            ContactNumber phoneHome = null;
            ContactNumber mobileHome = null;

            if (null != getDriver().getContactNumbers()) {
                for (ContactNumber phone : (Set<ContactNumber>) getDriver().getContactNumbers()) {
                    switch (phone.getPhoneType()) {
                        case HOME:
                            phoneHome = phone;
                            break;
                        case MOBILE:
                            mobileHome = phone;
                            break;
                    }
                }
            } else {
                setContactNumbers(new ArrayList<>());
            }

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

            getContactNumbers().add(
                    null == phoneHome
                            ? new ContactNumber(UUID.randomUUID().toString(), PhoneType.HOME)
                            : phoneHome
            );
            getContactNumbers().add(
                    null == mobileHome
                            ? new ContactNumber(UUID.randomUUID().toString(), PhoneType.MOBILE)
                            : mobileHome
            );

            if (null != getDriver().getReferences() && !getDriver().getReferences().isEmpty()) {
                ((Set<Reference>) getDriver().getReferences()).forEach((ref) -> {
                    Reference r = new Reference(ref.getId());

                    r.setReferenceType(ref.getReferenceType());
                    r.setPerson(new Person(getDriverId()));
                    r.setPhone(ref.getPhone());
                    r.setCompleteName(ref.getCompleteName());
                    r.setCompleteAddress(ref.getCompleteAddress());

                    getReferences().add(r);
                });
            } else {
                setSaveReferenceFirstTime(true);
                getReferences().add(new Reference());
                getReferences().add(new Reference());
            }

            getReferenceTypes().addAll(Arrays.asList(ReferenceType.values()));

            if (null != getDriver().getDocuments() && !getDriver().getDocuments().isEmpty()) {
                ((Set<Document>) getDriver().getDocuments()).forEach((Document doc) -> {
                    setDocument(doc);
                    setPhotoName(getBundlePropertyFile().getString("document.title")
                            + " " + doc.getFileName()
                            + " " + getBundlePropertyFile().getString("driver.document.add.success.desc"));
                });
            } else {
                setSavePhotoBtnOnclick(true);
                setDocument(new Document(DocumentType.SELFIE));
            }
        } catch (Exception e) {
            logger.info("init", e);
        }
    }

    public boolean isJuridico() {
        return juridico;
    }

    public void setJuridico(boolean juridico) {
        this.juridico = juridico;
    }

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

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

    public String getDriverId() {
        return driverId;
    }

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

    public Person getDriver() {
        return driver;
    }

    public void setDriver(Person driver) {
        this.driver = driver;
    }

    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 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 List<Reference> getReferences() {
        if (null == references) {
            references = new ArrayList<>();
        }
        return references;
    }

    public void setReferences(List<Reference> references) {
        this.references = references;
    }

    public List<ReferenceType> getReferenceTypes() {
        if (null == referenceTypes) {
            referenceTypes = new ArrayList<>();
        }
        return referenceTypes;
    }

    public void setReferenceTypes(List<ReferenceType> referenceTypes) {
        this.referenceTypes = referenceTypes;
    }

    public void setSaveReferenceFirstTime(boolean saveReferenceFirstTime) {
        this.saveReferenceFirstTime = saveReferenceFirstTime;
    }

    public boolean isSaveReferenceFirstTime() {
        return saveReferenceFirstTime;
    }

    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 isSavePhotoBtnOnclick() {
        return savePhotoBtnOnclick;
    }

    public void setSavePhotoBtnOnclick(boolean savePhotoBtnOnclick) {
        this.savePhotoBtnOnclick = savePhotoBtnOnclick;
    }

}
