/* ====================================================================
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2000-2001 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Apache" and "Apache Software Foundation" and
 *     "Apache Jetspeed" must not be used to endorse or promote products
 *    derived from this software without prior written permission. For
 *    written permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache" or
 *    "Apache Jetspeed", nor may "Apache" appear in their name, without
 *    prior written permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

package pf.cs.portal.portlets;

// Turbine stuff
import org.apache.turbine.util.RunData;
import org.apache.turbine.services.velocity.TurbineVelocity;
import org.apache.turbine.services.pull.TurbinePull;
import org.apache.turbine.modules.ActionLoader;

// Jetspeed stuff
import org.apache.jetspeed.portal.Portlet;
import org.apache.jetspeed.portal.portlets.AbstractPortlet;
import org.apache.jetspeed.portal.PortletException;
import org.apache.jetspeed.services.TemplateLocator;
import org.apache.jetspeed.services.JetspeedSecurity;
import org.apache.jetspeed.services.rundata.JetspeedRunData;

//import org.apache.jetspeed.util.template.PortletTemplateLink;
import pf.cs.portal.util.velocity.VelocityPortletTemplateLink;

// Ecs stuff
import org.apache.ecs.ConcreteElement;
import org.apache.ecs.ClearElement;

// Velocity Stuff
import org.apache.velocity.context.Context;
import org.apache.turbine.util.Log;

/**
 * An other Velocity based portlet implementation
 *
 */
public abstract class VelocityPortlet extends AbstractPortlet

{
    /**
     * Template name
     */
    private String aTemplate = null;
    
    /**
     * By default the data is non cacheable
     */
    public void init( ) throws PortletException {
        setCacheable( false );
    }
    
    /**
     * Returns an HTML representation of this portlet.
     */
    public ConcreteElement getContent( RunData rundata ) {
        
        //Are we allowed to see it?
        if (!JetspeedSecurity.checkPermission(rundata,
        JetspeedSecurity.PERMISSION_VIEW,
        this)) {
            return new ClearElement("Sorry, you have no permission to see this portlet");
        }
        
        // create a blank context and with all the global application
        // Pull Tools inside
        Context context = TurbineVelocity.getContext();
        context.put( "data", rundata );
        context.put( "portlet", this );
        context.put( "conf", this.getPortletConfig() );
        context.put( "skin", this.getPortletConfig().getPortletSkin() );
        //context.put( "jlink", new PortletTemplateLink(rundata,this) );
        context.put( "vlink", new VelocityPortletTemplateLink(rundata,this) );
        
        // Put the request and session based contexts
        TurbinePull.populateContext(context, rundata);
        
        // execute the action if it's found in the context for this portlet
        String actionName = getPortletAction(rundata);
        
        if (actionName != null) {
            // store the context so that the action can retrieve it
            Log.debug("VelocityPortlet " + getName() + " found action " + actionName + " context " + context);
            rundata.getTemplateInfo().setTemplateContext( "VelocityPortletContext", context );
            
            // if there is an action with the same name in modules/actions/portlets exec it
            try {
                ActionLoader.getInstance().exec( rundata, actionName );
            }
            catch( Exception e) {
                Log.error( e );
            }
        }
        
        
        // Check the portlet mode and build the appropriate context
        JetspeedRunData jdata = (JetspeedRunData)rundata;
        try {
            if  ( ( jdata.getMode()==jdata.CUSTOMIZE )
            && (this.getName().equals(jdata.getCustomized().getName())) ) {
                buildConfigureContext(context,rundata);
            }
            else {
                // we're maximized
                if ( jdata.getMode()==jdata.MAXIMIZE ) {
                    buildMaximizedContext(context,rundata);
                } else
                    // else is normal context
                    buildNormalContext(context,rundata);
            }
        }
        catch ( Exception e ) {
            Log.error( e );
            return null;
        }
        
        // generate the content
        String content = "";
        
        try {
            
            String template = getPortletTemplate(rundata);
            
            if (-1 == template.indexOf(".vm"))
                template = template + ".vm";
            
            String templatePath = TemplateLocator.locatePortletTemplate(rundata, template);
            TurbineVelocity.handleRequest(context, templatePath, rundata.getOut());
        }
        catch ( Exception e ) {
            Log.error( e );
            return null;
        }
        
        TurbineVelocity.requestFinished(context);
        
        if (content == null) content = "";
        
        return new ClearElement( content );
    }
    
    /**
     * Get portlet action name
     */
    public String getPortletAction(RunData rundata) {
        String actionName = rundata.getParameters().getString( getName() + "_action");
        return actionName;
    }
    
    /* 
     * Set the velocity template for the portlet.
     */
    public void setPortletTemplate( String template ) {
        aTemplate = template;
    }
    
    /**
     * Get the velocity template for the portlet.
     * This template can be define in the portlet
     * config by the "template" param in the registry
     * or set by the the method setTemplate( String template )
     */
    public String getPortletTemplate(RunData rundata) throws PortletException {
        
        // if the portlet template was set in the portlet
        if (aTemplate!=null)
            return aTemplate;
        
        // if the template was set in the run data (by used of VelocityPortletTemplateLink by exemple)
        String templateName = rundata.getParameters().getString( getName() + "_template");
        if (templateName!=null)
            return templateName;
            
        // check if it's in the portlet config
        String template = getPortletConfig().getInitParameter("template");
        if (template != null) {
            return template;
        }
        else
            throw new PortletException("No Velocity template define for the portlet " + getName() );
        
    }
    
    /**
     * Subclasses should override this method if they wish to
     * build specific content when maximized. Default behavior is
     * to do the same as normal content.
     */
    protected void buildMaximizedContext( Context context, RunData rundata )
    throws Exception {
        buildNormalContext( context, rundata);
    }
    
    /**
     * Subclasses should implements PortletCustomizer
     * interface and override this method if they wish to
     * provide their own customization behavior.
     * Default is to use the default CustomizePortlet
     */
    protected void buildConfigureContext( Context context, RunData rundata )
    throws Exception {
    }
    
    /**
     * Subclasses must override this method to provide default behavior
     * for the portlet
     */
    protected abstract void buildNormalContext( Context context, RunData rundata )
    throws Exception;
}

