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

import com.arrebol.taxiservicios.beans.TaxiGenericBean;
import com.arrebol.taxiservicios.beans.admin.employee.EmployeeAddBean;
import com.arrebol.taxiservicios.controller.system.UserController;
import com.arrebol.taxiservicios.controller.top.ProfileService;
import com.arrebol.taxiservicios.controller.util.DateWrapper;
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.PhoneType;
import java.io.IOException;
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.enterprise.context.RequestScoped;
import javax.faces.application.FacesMessage;
import javax.faces.context.ExternalContext;
import javax.inject.Inject;
import javax.inject.Named;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

/**
 *
 * @author Picasso
 */
@Named
@RequestScoped
public class ProfileBean extends TaxiGenericBean implements Serializable {

    private static final String LOGIN = "/dashboard.jsf";

    /**
     *
     * @param avatarSelected
     */
    public void updateAvatar(String avatarSelected) {
        try {
            if (profileService.updateAvatar(getEmployee().getId(), avatarSelected)) {
                getEmployee().setAvatar(avatarSelected);
                getLoggedUser().getPerson().setAvatar(getEmployee().getAvatar());

                setLoggedUser(getLoggedUser());

                showMessage(FacesMessage.SEVERITY_INFO,
                        getBundlePropertyFile().getString("employee.edit.title"),
                        getBundlePropertyFile().getString("employee.edit.avatar.success.desc"));
            } else {
                logger.error("Avatar was not updated");
                showMessage(FacesMessage.SEVERITY_ERROR,
                        getBundlePropertyFile().getString("employee.edit.title"),
                        getBundlePropertyFile().getString("employee.edit.avatar.fail.desc"));
            }
        } catch (Exception e) {
            logger.error("updateAvatar: " + e);
            showMessage(FacesMessage.SEVERITY_FATAL,
                    getBundlePropertyFile().getString("employee.edit.title"),
                    getBundlePropertyFile().getString("employee.edit.avatar.exception.desc"));
        }

    }

    public void locationUpdate() {
        logger.info("locationUpdate");
        try {
            getEmployee().setLastUpdatedBy(new User(getLoggedUser().getId(), ""));
            getEmployee().setLastUpdatedOn(DateWrapper.today().subtractHours(6).asDate());
            getEmployee().setLocation(new Location(locationId));
            if (profileService.updatePersonById(getEmployee())) {
                showMessage(FacesMessage.SEVERITY_INFO,
                        getBundlePropertyFile().getString("employee.edit.title"),
                        getBundlePropertyFile().getString("employee.edit.success.desc"));

                UserController userCtrl = new UserController();
                userCtrl.updateUserLocation(getLoggedUser().getId(), locationId);

                try {
                    ExternalContext externalContext = externalContext();

                    externalContext.invalidateSession();
                    externalContext.redirect(externalContext.getRequestContextPath() + LOGIN);
                } catch (IOException e) {
                    logger.error("logout() - " + e);
                }

            } else {
                logger.error("Employee " + getEmployee() + " was not updated");
                showMessage(FacesMessage.SEVERITY_ERROR,
                        getBundlePropertyFile().getString("employee.edit.title"),
                        getBundlePropertyFile().getString("employee.edit.fail.desc"));
            }
        } catch (Exception e) {
            logger.error("selfUpdate: " + e);
            showMessage(FacesMessage.SEVERITY_FATAL,
                    getBundlePropertyFile().getString("employee.edit.title"),
                    getBundlePropertyFile().getString("employee.edit.exception.desc"));
        }
    }

    /**
     * Save/Update an employee in the system.
     */
    public void selfUpdate() {
        logger.info("selfUpdate");
        try {
            getEmployee().setLastUpdatedBy(new User(getLoggedUser().getId(), ""));
            getEmployee().setLastUpdatedOn(DateWrapper.today().subtractHours(6).asDate());

            if (profileService.updatePersonById(getEmployee())) {
                showMessage(FacesMessage.SEVERITY_INFO,
                        getBundlePropertyFile().getString("employee.edit.title"),
                        getBundlePropertyFile().getString("employee.edit.success.desc"));

            } else {
                logger.error("Employee " + getEmployee() + " was not updated");
                showMessage(FacesMessage.SEVERITY_ERROR,
                        getBundlePropertyFile().getString("employee.edit.title"),
                        getBundlePropertyFile().getString("employee.edit.fail.desc"));
            }
        } catch (Exception e) {
            logger.error("selfUpdate: " + e);
            showMessage(FacesMessage.SEVERITY_FATAL,
                    getBundlePropertyFile().getString("employee.edit.title"),
                    getBundlePropertyFile().getString("employee.edit.exception.desc"));
        }
    }

    /**
     * Add RFC, Email, CURP, and Local/Mobile phones to employee.
     */
    public void mergeContactDetails() {
        logger.info("mergeContactDetails");
        try {
            getEmployee().setLastUpdatedBy(new User(getLoggedUser().getId(), ""));
            getEmployee().setLastUpdatedOn(DateWrapper.today().subtractHours(6).asDate());

            getNumbers().forEach(phone -> {
                phone.setPerson(new Person(getEmployee().getId()));
                switch (phone.getPhoneType()) {
                    case HOME:
                        if (isSaveLocalNumber()) {
                            phone.setCreatedBy(new User(getLoggedUser().getId(), ""));
                            phone.setCreatedOn(DateWrapper.today().subtractHours(6).asDate());
                        } else {
                            phone.setLastUpdatedBy(new User(getLoggedUser().getId(), ""));
                            phone.setLastUpdatedOn(DateWrapper.today().subtractHours(6).asDate());
                        }
                        break;
                    case MOBILE:
                        if (isSaveMobile()) {
                            phone.setCreatedBy(new User(getLoggedUser().getId(), ""));
                            phone.setCreatedOn(DateWrapper.today().subtractHours(6).asDate());
                        } else {
                            phone.setLastUpdatedBy(new User(getLoggedUser().getId(), ""));
                            phone.setLastUpdatedOn(DateWrapper.today().subtractHours(6).asDate());
                        }
                        break;
                }
            });

            if (profileService.updateEmployeeContactDetailsById(getEmployee(), getNumbers())) {
                logger.info("Contact detais merged.");
                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 merged.");
                logger.error("Contact details: " + getEmployee());
                logger.error("Numbers details: " + getNumbers());
                showMessage(FacesMessage.SEVERITY_ERROR,
                        getBundlePropertyFile().getString("person.add.contact.title"),
                        getBundlePropertyFile().getString("person.add.contact.fail.desc"));
            }
        } catch (Exception e) {
            logger.error("mergeContactDetails: " + e);

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

    /**
     * Save/Update employee address details.
     */
    public void mergeAddress() {
        logger.info("mergeAddress");
        try {
            getAddress().setStreet(facesContext().getExternalContext().getRequestParameterMap().get("mergeAddressForm:streetHdn"));
            getAddress().setExtendedAddress(facesContext().getExternalContext().getRequestParameterMap().get("mergeAddressForm:colonyHdn"));
            getAddress().setLocality(facesContext().getExternalContext().getRequestParameterMap().get("mergeAddressForm:departmentHdn"));
            getAddress().setRegion(facesContext().getExternalContext().getRequestParameterMap().get("mergeAddressForm:stateHdn"));
            getAddress().setZipCode(facesContext().getExternalContext().getRequestParameterMap().get("mergeAddressForm:cpHdn"));

            getAddress().setPerson(new Person(getEmployee().getId()));

            if (isSaveAddress()) {
                getAddress().setCreatedOn(DateWrapper.today().subtractHours(6).asDate());
                getAddress().setCreatedBy(new User(getLoggedUser().getId(), ""));
            } else {
                getAddress().setLastUpdatedOn(DateWrapper.today().subtractHours(6).asDate());
                getAddress().setLastUpdatedBy(new User(getLoggedUser().getId(), ""));
            }

            if (profileService.saveOrUpdateAddress(getAddress())) {
                logger.info("Address detais saved.");

                setSaveAddress(false);
                showMessage(FacesMessage.SEVERITY_INFO,
                        getBundlePropertyFile().getString("person.edit.address.title"),
                        getBundlePropertyFile().getString("person.edit.address.success.desc"));
            } else {
                logger.error("Address details were not merged " + getAddress());

                showMessage(FacesMessage.SEVERITY_ERROR,
                        getBundlePropertyFile().getString("person.edit.address.title"),
                        getBundlePropertyFile().getString("person.edit.address.fail.desc"));
            }

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

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

    private static final long serialVersionUID = -8049783256162682907L;
    //private static final String AVATAR_NAME = "images/avatar/avatar-";
    //private static final String AVATAR_EXT = ".png";

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

    @Inject
    private ProfileService profileService;

    private Person employee;
    private List<ContactNumber> numbers;
    private Address address;
    private Date sixteenYearsOld;
    private boolean saveMobile;
    private boolean saveLocalNumber;
    private boolean saveAddress;
    private boolean saveContactDetails;
    private List<String> avatars;
    private String locationId;

    @PostConstruct
    public void init() {
        logger.info("init, user " + getLoggedUser().getPerson().getId());

        loadBundlePropertyFile();

        setNumbers(new ArrayList<>());
        setEmployee(profileService.getEmployeeById(getLoggedUser().getPerson().getId()));
        setLocationId(getEmployee().getLocation().getId());

        if (null != getEmployee().getAddresses() && !getEmployee().getAddresses().isEmpty()) {
            ((Set<Address>) getEmployee().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 != getEmployee().getContactNumbers() && !getEmployee().getContactNumbers().isEmpty()) {
            for (ContactNumber phone : (Set<ContactNumber>) getEmployee().getContactNumbers()) {
                switch (phone.getPhoneType()) {
                    case HOME:
                        phoneHome = phone;
                        break;
                    case MOBILE:
                        mobileHome = phone;
                        break;
                }
            }
        }

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

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

//        for (int i = 1; i <= 4; i++) {
        //          getAvatars().add(new Avatar(AVATAR_NAME + i + AVATAR_EXT));
        //    }
    }

    public Person getEmployee() {
        return employee;
    }

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

    public List<ContactNumber> getNumbers() {
        return numbers;
    }

    public void setNumbers(List<ContactNumber> numbers) {
        this.numbers = numbers;
    }

    public Address getAddress() {
        return address;
    }

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

    public Date getSixteenYearsOld() {
        if (null == sixteenYearsOld) {
            Calendar calendar = Calendar.getInstance();

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

        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 boolean isSaveContactDetails() {
        return saveContactDetails;
    }

    public void setSaveContactDetails(boolean saveContactDetails) {
        this.saveContactDetails = saveContactDetails;
    }

    public List<String> getAvatars() {
        if (null == avatars) {
            avatars = new ArrayList<>();

            avatars.add("images/avatar/female-power/female-1.png");
            avatars.add("images/avatar/female-power/female-2.png");
            avatars.add("images/avatar/female-power/female-3.png");
            avatars.add("images/avatar/female-power/female-4.png");
            avatars.add("images/avatar/female-power/female-5.png");

            avatars.add("images/avatar/green-power/green-1.png");
            avatars.add("images/avatar/green-power/green-2.png");
            avatars.add("images/avatar/green-power/green-3.png");
            avatars.add("images/avatar/green-power/green-4.png");

            avatars.add("images/avatar/man-power/man-1.png");
            avatars.add("images/avatar/man-power/man-2.png");
            avatars.add("images/avatar/man-power/man-3.png");
            avatars.add("images/avatar/man-power/man-4.png");
            avatars.add("images/avatar/man-power/man-5.png");

            avatars.add("images/avatar/mask-power/mask-1.png");
            avatars.add("images/avatar/mask-power/mask-2.png");
            avatars.add("images/avatar/mask-power/mask-3.png");
            avatars.add("images/avatar/mask-power/mask-4.png");
        }
        return avatars;
    }

    public void setAvatars(List<String> avatars) {
        this.avatars = avatars;
    }

    public String getLocationId() {
        return locationId;
    }

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

}
