/*
 * ICESOFT COMMERCIAL SOURCE CODE LICENSE V 1.1
 *
 * The contents of this file are subject to the ICEsoft Commercial Source
 * Code License Agreement V1.1 (the "License"); you may not use this file
 * except in compliance with the License. You may obtain a copy of the
 * License at
 * http://www.icesoft.com/license/commercial-source-v1.1.html
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
 * License for the specific language governing rights and limitations under
 * the License.
 *
 * Copyright 2009-2015 ICEsoft Technologies Canada, Corp. All Rights Reserved.
 */
package com.icesoft.faces.facelets.component.select;

import javax.faces.application.Application;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import javax.faces.event.ValueChangeEvent;
import javax.faces.model.SelectItem;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;

/**
 * <p>The LocaleController is responsible for keeping track of and changing the
 * current application locale.
 * The available languages are identified by the lowercase ISO 639 code appended
 * to a resource bundle properties file ie: messages_es.properties. Languages
 * can also have a country associated with them ie: messages_en_US.properties.
 * If there is no resource bundle available or one language is available, making
 * a selection is not necessary and the component will not be rendered.</p>
 */
@SessionScoped
@ManagedBean
public class LocaleController implements Serializable {

    // Locale bound to the view tag
    private Locale sessionLocale;
    // SelectItem List of available locales in the application
    private ArrayList<SelectItem> applicationLocales = new ArrayList<SelectItem>();
    // Currently selected language, an empty String or a lowercase ISO 639 code
    // This code can also have an ISO 3166 2-letter country code appended
    private String sessionLanguage;
    // If there is more than one locale, render the component
    private boolean multipleLocales;

    public LocaleController() {
        Application application = FacesContext.getCurrentInstance().getApplication();
        sessionLocale = application.getDefaultLocale();
        sessionLanguage = sessionLocale.getLanguage();
        Iterator supportedLocales = application.getSupportedLocales();
        // Populate SelectItems with available locales
        while (supportedLocales.hasNext()) {
            Locale locale = (Locale) supportedLocales.next();
            // Add the country to the String if it has been specified
            if (locale.getCountry().length() > 0) {
                applicationLocales.add(new SelectItem(locale.getLanguage() + "_" + locale.getCountry(), locale.getDisplayName()));
            } else {
                applicationLocales.add(new SelectItem(locale.getLanguage(), locale.getDisplayName()));
            }
        }
        // Only render the component if there are multiple languages
        if (applicationLocales.size() > 1) {
            multipleLocales = true;
        }
    }

    /**
     * Change the session locale.
     *
     * @param event jsf value change event.
     */
    public void localeValueChange(ValueChangeEvent event) {
        sessionLanguage = (String) event.getNewValue();
        // Create the Locale object with the country, if it has been specified
        if (sessionLanguage.contains("_")) {
            String[] languageAndCountry = sessionLanguage.split("_");
            sessionLocale = new Locale(languageAndCountry[0], languageAndCountry[1]);
        } else {
            sessionLocale = new Locale(sessionLanguage);
        }
        FacesContext.getCurrentInstance().getViewRoot().setLocale(sessionLocale);
    }

    public Locale getSessionLocale() {
        return sessionLocale;
    }

    public void setSessionLocale(Locale sessionLocale) {
        this.sessionLocale = sessionLocale;
    }

    public List getApplicationLocales() {
        return applicationLocales;
    }

    public void setApplicationLocales(ArrayList<SelectItem> applicationLocales) {
        this.applicationLocales = applicationLocales;
    }

    public String getSessionLanguage() {
        return sessionLanguage;
    }

    public void setSessionLanguage(String sessionLanguage) {
        this.sessionLanguage = sessionLanguage;
    }

    public boolean isMultipleLocales() {
        return multipleLocales;
    }

    public void setMultipleLocales(boolean multipleLocales) {
        this.multipleLocales = multipleLocales;
    }
}
