/*
 * Copyright 2003,2004 The Apache Software Foundation.
 * 
 * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.pluto.internal.impl;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Vector;

import javax.portlet.PortletPreferences;
import javax.portlet.PreferencesValidator;
import javax.portlet.ReadOnlyException;
import javax.portlet.ValidatorException;

import org.apache.pluto.Constants;
import org.apache.pluto.PortletContainer;
import org.apache.pluto.PortletContainerException;
import org.apache.pluto.util.StringManager;
import org.apache.pluto.internal.InternalPortletPreference;
import org.apache.pluto.internal.InternalPortletRequest;
import org.apache.pluto.internal.InternalPortletWindow;
import org.apache.pluto.internal.PortletEntity;
import org.apache.pluto.spi.optional.PortletPreferencesService;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.logging.Log;

/**
 * Implementation of the <code>javax.portlet.PortletPreferences</code>
 * interface.
 * 
 * @see org.apache.pluto.core.PortletPreference
 * @see org.apache.pluto.core.impl.PortletPreferenceImpl
 * 
 * @author <a href="mailto:ddewolf@apache.org">David H. DeWolf</a>
 * @author <a href="mailto:zheng@apache.org">ZHENG Zhong</a>
 */
public class PortletPreferencesImpl implements PortletPreferences {
	
	/** Logger. */
    private static final Log LOG = LogFactory.getLog(PortletPreferencesImpl.class);
    
    private static final StringManager EXCEPTIONS = StringManager.getManager(
    		PortletPreferencesImpl.class.getPackage().getName());
    
    
    // Private Member Variables ------------------------------------------------
    
    /** The portlet preferences service provided by the portal. */
    private PortletPreferencesService preferencesService = null;

    private InternalPortletWindow window = null;

    private InternalPortletRequest request = null;
    
    /**
     * Default portlet preferences retrieved from portlet.xml, and used for
     * resetting portlet preferences.
     */
    private InternalPortletPreference[] defaultPreferences = null;
    
    /**
     * Current portlet preferences: key is the preference name as a string,
     * value is the PortletPreference instance.
     */
    private Map preferences = new HashMap();

    /** Current method used for managing these preferences. */
    private Integer methodId = null;
    
    
    // Constructor -------------------------------------------------------------
    
    /**
     * Constructs an instance.
     * @param container  the portlet container.
     * @param portletWindow  the internal portlet window.
     * @param request  the internal portlet request.
     * @param methodId  the request method ID: render request or action request.
     */
    public PortletPreferencesImpl(PortletContainer container,
                                  InternalPortletWindow window,
                                  InternalPortletRequest request,
                                  Integer methodId) {
        this.window = window;
        this.request = request;
        this.methodId = methodId;
        
        // Get the portlet preferences service from container.
        preferencesService = container.getOptionalContainerServices()
        		.getPortletPreferencesService();
        if (LOG.isDebugEnabled()) {
            LOG.debug("Using PortletPreferencesService: "
            		+ preferencesService.getClass().getName());
        }
        
        // Put default portlet preferences into preferences map.
        PortletEntity entity = window.getPortletEntity();
        defaultPreferences = entity.getDefaultPreferences();
        for (int i = 0; i < defaultPreferences.length; i++) {
            preferences.put(defaultPreferences[i].getName(),
                            (InternalPortletPreference) defaultPreferences[i].clone());
        }
        if (LOG.isDebugEnabled()) {
        	LOG.debug("Loaded default preferences: " + toString());
        }
        
        // Merge stored portlet preferences into preferences map.
        try {
        	InternalPortletPreference[] storedPreferences = preferencesService
            		.getStoredPreferences(window, request);
            for (int i = 0; i < storedPreferences.length; i++) {
            	if (LOG.isDebugEnabled()) {
            		LOG.debug("Merging stored preference: "
            				+ storedPreferences[i].getName());
            	}
                preferences.put(storedPreferences[i].getName(),
                                storedPreferences[i]);
            }
        	// Store the preferences retrieved from portlet.xml.
            //   Portlet preferences are stored everytime when a
            //   PortletPreferencesImpl instance is created.
            //   So here we do not check the portlet request method ID.
        	internalStore();
        	
        } catch (PortletContainerException ex) {
            LOG.error("Error retrieving preferences.", ex);
            //TODO: Rethrow up the stack????
        } catch (IOException ex) {
            LOG.error("Error retrieving preferences.", ex);        	
            //TODO: Rethrow up the stack????
        } catch (ValidatorException ex) {
            LOG.warn("ValidatorException initializing portlet preferences. "
            		+ "This is not illegal at this point "
            		+ "since we are just retreiving from portlet.xml.", ex);    	
        }
        if (LOG.isDebugEnabled()) {
        	LOG.debug("Merged stored preferences: " + toString());
        }
    }
    
    
    // PortletPreferences Impl -------------------------------------------------
    
    public boolean isReadOnly(String key) {
        if (key == null) {
            throw new IllegalArgumentException(
            		EXCEPTIONS.getString("error.null", "Preference key "));
        }
        InternalPortletPreference pref = (InternalPortletPreference)
        		preferences.get(key);
        return (pref != null && pref.isReadOnly());
    }

    public String getValue(String key, String defaultValue) {
        String[] values = getValues(key, new String[] { defaultValue });
        String value = null;
        if (values != null && values.length > 0) {
        	value = values[0];
        }
        if (value == null) {
        	value = defaultValue;
        }
        return value;
    }

    public String[] getValues(String key, String[] defaultValues) {
        if (key == null) {
            throw new IllegalArgumentException(
            		EXCEPTIONS.getString("error.null", "Preference key "));
        }
        String[] values = null;
        InternalPortletPreference pref = (InternalPortletPreference)
        		preferences.get(key);
        if (pref != null) {
            values = pref.getValues();
        }
        if (values == null) {
            values = defaultValues;
        }
        return values;
    }

    public void setValue(String key, String value) throws ReadOnlyException {
        if (isReadOnly(key)) {
            throw new ReadOnlyException(EXCEPTIONS.getString(
            		"error.preference.readonly", key));
        }
        InternalPortletPreference pref = (InternalPortletPreference)
        		preferences.get(key);
        if (pref != null) {
            pref.setValues(new String[] { value });
        } else {
            pref = new PortletPreferenceImpl(key, new String[] { value });
            preferences.put(key, pref);
        }
    }

    public void setValues(String key, String[] values) throws ReadOnlyException {
        if (isReadOnly(key)) {
            throw new ReadOnlyException(EXCEPTIONS.getString(
            		"error.preference.readonly"));
        }
        InternalPortletPreference pref = (InternalPortletPreference)
        		preferences.get(key);
        if (pref != null) {
            pref.setValues(values);
        } else {
            pref = new PortletPreferenceImpl(key, values);
            preferences.put(key, pref);
        }
    }

    public Enumeration getNames() {
        return new Vector(preferences.keySet()).elements();
    }

    public Map getMap() {
        Map map = new HashMap();
        Iterator it = preferences.keySet().iterator();
        while (it.hasNext()) {
        	InternalPortletPreference pref = (InternalPortletPreference)
        			preferences.get(it.next());
            map.put(pref.getName(),
                    pref.getValues() != null ? pref.getValues().clone() : null);
        }
        return Collections.unmodifiableMap(map);
    }
    
    public void reset(String key) throws ReadOnlyException {
    	// Read-only preferences cannot be reset.
        if (isReadOnly(key)) {
            throw new ReadOnlyException(EXCEPTIONS.getString(
            		"error.preference.readonly", "Preference key "));
        }
        // Try to reset preference to the default values.
        boolean resetDone = false;
        for (int i = 0; !resetDone && i < defaultPreferences.length; i++) {
        	if (key.equals(defaultPreferences[i].getName())) {
        		if (LOG.isDebugEnabled()) {
        			LOG.debug("Resetting preference for key: " + key);
        		}
        		preferences.put(key,
        				(InternalPortletPreference) defaultPreferences[i].clone());
        		resetDone = true;
        	}
        }
        // Remove preference if default values are not defined (PLT.14.1).
        if (!resetDone) {
        	if (LOG.isDebugEnabled()) {
        		LOG.debug("Resetting preference to null for key: " + key);
        	}
        	preferences.remove(key);
        }
    }
    
    /**
     * Stores the portlet preferences to a persistent storage. This method
     * should only be invoked within <code>processAction()</code> method.
     * 
     * @see #internalStore()
     * 
     * @throws IllegalStateException  if this method is not invoked within
     *         <code>processAction()</code> method.
     * @throws ValidatorException  if the portlet preferences are not valid.
     * @throws IOException  if an error occurs with the persistence mechanism.
     */
    public void store() throws IOException, ValidatorException {
        if (!Constants.METHOD_ACTION.equals(methodId)) {
            throw new IllegalStateException(
                	"store is only allowed inside a processAction call.");
        }
        internalStore();
    }
    
    
    // Private Methods ---------------------------------------------------------
    
    /**
     * Stores the portlet preferences to a persistent storage. If a preferences
     * validator is defined for this portlet, this method firstly validates the
     * portlet preferences.
     * <p>
     * This method is invoked internally, thus it does not check the portlet
     * request method ID (METHOD_RENDER or METHOD_ACTION).
     * </p>
     * @throws ValidatorException  if the portlet preferences are not valid.
     * @throws IOException  if an error occurs with the persistence mechanism.
     */
    private void internalStore() throws IOException, ValidatorException {
        // Validate the preferences before storing, if a validator is defined.
        //   If the preferences cannot pass the validation,
        //   an ValidatorException will be thrown out.
        PreferencesValidator validator = window.getPortletEntity()
        		.getPreferencesValidator();
        if (validator != null) {
        	validator.validate(this);
        }
        // Store the portlet preferences.
        InternalPortletPreference[] prefs = (InternalPortletPreference[]) 
        		(new ArrayList(preferences.values())).toArray(
        				new InternalPortletPreference[preferences.size()]);
        try {
        	preferencesService.store(window, request, prefs);
        } catch (PortletContainerException ex) {
            LOG.error("Error storing preferences.", ex);
            throw new IOException("Error storing perferences: " + ex.getMessage());
        }
    }
    
    
    // Object Methods ----------------------------------------------------------
    
    /**
     * Returns the string representation of this object. Preferences are
     * separated by ';' character, while values in one preference are separated
     * by ',' character.
     * @return the string representation of this object.
     * @see java.lang.Object#toString()
     */
    public String toString() {
    	StringBuffer buffer = new StringBuffer();
    	buffer.append(getClass().getName()).append("[");
    	for (Enumeration en = getNames(); en.hasMoreElements(); ) {
    		String name = (String) en.nextElement();
    		buffer.append(name);
    		buffer.append("(readOnly:").append(isReadOnly(name)).append(")=");
    		String[] values = getValues(name, null);
    		if (values != null) {
	    		for (int i = 0; i < values.length; i++) {
	    			buffer.append(values[i]);
	    			if (i < values.length - 1) {
	    				buffer.append(",");
	    			}
				}
    		} else {
    			buffer.append("NULL");
    		}
    		buffer.append(";");
    	}
    	buffer.append("]");
    	return buffer.toString();
    }
    
}
