package de.proveo.rts.web.portlet.util;

import java.io.IOException;
import java.util.ResourceBundle;

import javax.faces.FacesException;
import javax.faces.context.FacesContext;
import javax.faces.el.ValueBinding;
import javax.faces.model.SelectItem;
import javax.portlet.ActionResponse;
import javax.portlet.PortletMode;
import javax.portlet.PortletModeException;
import javax.portlet.PortletPreferences;
import javax.portlet.PortletRequest;
import javax.portlet.PortletResponse;
import javax.portlet.PortletSession;
import javax.portlet.ReadOnlyException;
import javax.portlet.RenderResponse;
import javax.portlet.ValidatorException;
import javax.portlet.WindowState;
import javax.portlet.WindowStateException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jfree.chart.ChartRenderingInfo;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.entity.StandardEntityCollection;

import de.proveo.rts.web.i18n.LanguageUtil;
import de.proveo.rts.web.managedBeans.common.data.SessionDataBean;
import de.proveo.rts.web.util.RtsUtil;

public class RtsPortletUtil {

	private static final Log log = LogFactory.getLog(RtsPortletUtil.class);
	
	private static ResourceBundle currentPortletBundle;

	public static PortletRequest getPortletRequest() {
		FacesContext facesContext = FacesContext.getCurrentInstance();
		PortletRequest request = null;
		if (facesContext.getExternalContext().getRequest() instanceof PortletRequest) {
			request = (PortletRequest) facesContext.getExternalContext()
					.getRequest();
		}
		return request;
	}

	public static PortletResponse getPortletResponse() {
		FacesContext facesContext = FacesContext.getCurrentInstance();
		PortletResponse response = null;
		if (facesContext.getExternalContext().getRequest() instanceof PortletRequest) {
			response = (PortletResponse) facesContext.getExternalContext()
					.getResponse();
		}
		return response;
	}

	public static WindowState getWindowState() {
		return getPortletRequest().getWindowState();
	}

	public static PortletSession getPortletSession() {
		return getPortletRequest().getPortletSession();
	}

	public static String getPreference(String attr, String def) {
		return getPortletRequest().getPreferences().getValue(attr, def);
	}

	public static String getPreference(String attr) {
		return getPortletRequest().getPreferences().getValue(attr, "");
	}

	public static PortletPreferences getPortletPreferences() {
		return getPortletRequest().getPreferences();
	}
	
	public static PortletMode getPortletMode()
	{
		return getPortletRequest().getPortletMode();
	}

	public static void setPreference(String attr, String def) {
		try {
			PortletPreferences pref = getPortletPreferences();
			pref.setValue(attr, def);
			pref.store();

		} catch (ReadOnlyException e) {
			log.error("runs into", e);
		} catch (ValidatorException e) {
			log.error("runs into", e);
		} catch (IOException e) {
			log.error("runs into", e);
		}
	}

	public static void setPreferences(String attr, Object[] defs) {

		String[] strArr = new String[defs.length];

		for (int i = 0; i < defs.length; i++) {
			strArr[i] = String.valueOf(defs[i]);
		}

		setPreferences(attr, strArr);
	}

	public static void setPreferences(String attr, String[] defs) {
		try {
			PortletPreferences pref = getPortletPreferences();
			pref.setValues(attr, defs);
			pref.store();

		} catch (ReadOnlyException e) {
			log.error("runs into", e);
		} catch (ValidatorException e) {
			log.error("runs into", e);
		} catch (IOException e) {
			log.error("runs into", e);
		}
	}

	public static String[] getPreferences(String attr) {
		return getPortletPreferences().getValues(attr, null);
	}

	public static Long[] getPreferencesAsLong(String attr) {

		String[] strArr = getPreferences(attr);

		if (strArr == null)
			return null;

		Long[] arr = new Long[strArr.length];

		for (int i = 0; i < strArr.length; i++) {
			arr[i] = Long.parseLong(strArr[i]);
		}

		return arr;
	}

	public static String createChartUrl(JFreeChart chart, int imageWidth,
			int imageHeight, boolean imageMap) {
		String file = null;
		log.debug("createChartUrl called");

		if (chart != null) {

			PortletSession session = getPortletSession();

			// ImageMap Rendering Info
			ChartRenderingInfo info = new ChartRenderingInfo(
					new StandardEntityCollection());

			try {
				file = ChartPortletUtilities.saveChartAsPNG(chart, imageWidth,
						imageHeight, info, session);

				if (log.isDebugEnabled())
					log.debug("Generated Chart Filename :" + file);

				if (imageMap) {
					writeImageMap(file, info);
				}

			} catch (IOException e) {
				log.error("runs into", e);
			}
		}
		return file;
	}

	public static void writeImageMap(String file, ChartRenderingInfo info) {
		if (log.isDebugEnabled())
			log.debug("writeImageMap called with file: " + file);

		FacesContext context = FacesContext.getCurrentInstance();

		if (context.getExternalContext().getResponse() instanceof RenderResponse) {
			RenderResponse response = (RenderResponse) context
					.getExternalContext().getResponse();

			try {
				ChartUtilities.writeImageMap(response.getWriter(), file, info,
						true);

			} catch (IOException e) {
				log.error("cannot write image map", e);
			}
		}
	}

	public static void toViewMode() {
		try {
			ActionResponse actionResponse = (ActionResponse) RtsPortletUtil
					.getPortletResponse();
			actionResponse.setPortletMode(PortletMode.VIEW);
			actionResponse.setWindowState(WindowState.NORMAL);
		} catch (PortletModeException e) {
			log.error("runs into", e);
		} catch (WindowStateException e) {
			log.error("runs into", e);
		}
	}

	public static void toEditMode() {
		try {
			ActionResponse actionResponse = (ActionResponse) RtsPortletUtil
					.getPortletResponse();
			actionResponse.setPortletMode(PortletMode.EDIT);
			actionResponse.setWindowState(WindowState.MAXIMIZED);
		} catch (PortletModeException e) {
			log.error("runs into", e);
		} catch (WindowStateException e) {
			log.error("runs into", e);
			;
		}
	}
	
	public static boolean isEditMode()
	{
		return getPortletRequest().getPortletMode().equals(PortletMode.EDIT);
	}
	
	public static boolean isWindowMaximized()
	{
		return getPortletRequest().getWindowState().equals(WindowState.MAXIMIZED);
	}
	
	public static String getPortletBundleResource(String bundleResource)
	{
		String resource;
		try
		{
			resource = getPortletBundle().getString(bundleResource).trim();
		}
		catch(java.util.MissingResourceException e)
		{
			resource = "MISSING_RESOURCE: " + bundleResource;
		}
		return resource;
	}
	
	public static ResourceBundle getPortletBundle()
	{
		if(currentPortletBundle == null)
		{
			currentPortletBundle = ResourceBundle.getBundle("rts_portlet", LanguageUtil.getLocale());
		}
		return currentPortletBundle;
	}
	
	public static String getPortletName()
	{
		String portletName = (String) getPortletRequest().getPortletSession()
														 .getAttribute("portletName");
		if(portletName != null)
			return portletName;
		
		return "";
	}
	
	public static FacesContext getContext()
	{
		FacesContext context = FacesContext.getCurrentInstance();
		if (context == null)
		{
			log.error("getContext: No faces context found.");
			throw new FacesException("No faces context found.");
		}
		return context;
	}
	
	public static ValueBinding getBinding(String vbString)
	{
		String el = String.format("#{%s}", vbString);
		ValueBinding binding = getContext().getApplication().createValueBinding(el);
		if (binding == null)
		{
			log.debug("getBinding: Could not create ValueBinding: " + el);
			throw new FacesException("Could not create ValueBinding: " + el);
		}
		return binding;
	}
	
	public static Object getManagedBean(String vbString)
	{
		FacesContext context = getContext();
		ValueBinding binding = getBinding(vbString);
		Object result = binding.getValue(context);
		if (result == null)
		{
			log.error("getManagedBean: Could not get the Object: " + vbString);
			//throw new FacesException("Could not get the Object: " + vbString);
		}
		return result;
	}
	
	public static SessionDataBean getSessionDataBean()
	{
		return (SessionDataBean)getManagedBean("sessionData");
	}
	
	public static SelectItem[] getStatusModels()
	{
		return getSessionDataBean().getStatusModels();
	}

}
