// Copyright (c) 2001 Oracle Corporation
package oracle.portal.sample.v2.devguide.samplerenderer;

import java.io.*;
import java.net.URLEncoder;
import oracle.portal.provider.v2.*;
import oracle.portal.provider.v2.http.*;
import oracle.portal.provider.v2.render.*;
import oracle.portal.provider.v2.render.http.HttpPortletRendererUtil;
import oracle.portal.provider.v2.personalize.NameValuePersonalizationObject;
import oracle.portal.provider.v2.security.AccessControlException;

/**
 * SampleRenderer is a default implementation of the {@link PortletRenderer}
 * interface. It supports all render modes, displaying a default message as the
 * mode's contents, with customization of the portlet's title using {@link
 * FilePersonalizationManager}.<p>
 *
 * SampleRenderer is intended to be used as a <i>head start</i> for developers
 * who wish to write their own implementations of the the {@link
 * PortletRenderer} interface. Developers may either subclass or directly edit
 * SampleRenderer to have it render their required contents.
 */
public class SampleRenderer extends PortletRenderer
{
    private long mSleepTime = -1;

    /**
     * Set a sleep time for a portlet using this renderer. This is used to 
     * demonstrate the thread monitor which is used to check how long requests
     * are taking compared to warning and maximum timeouts set in the provider
     * properties.
     */
    public void setSleepTime(String time)
    {
        try
        {
            long sleepTime = Long.parseLong(time);
            mSleepTime = sleepTime;
        }
        catch (NumberFormatException nfe){}
    }

    /**
     * Renders the appropriate header, contents and footer for the request by
     * delegating, based on render mode, to the appropriate methods.
     *
     * @param pr a PortletRenderRequest.
     */
    public void render(PortletRenderRequest pr)
        throws PortletException, AccessControlException
    {
        // make sure we set the content type before getting the Writer.
        decideContentType(pr);
 
        // Sleep at this stage if the sleepTime tag has been set in the
        // provider properties file. This is used to demonstrate the thread
        // monitor in operation.
        if (mSleepTime > -1)
        {
            try
            {
                Thread.sleep(mSleepTime);
            }
            catch (InterruptedException ie) {}
        }

        try
        {
            if( (pr.getMode() == PortletRenderer.MODE_EDIT ||
                 pr.getMode() == PortletRenderer.MODE_EDIT_DEFAULTS)
                && hasCustomizeAction(pr) )
            {
                handleEditData(pr);
                return;
            }
            renderPortletHeader(pr);
            switch(pr.getMode())
            {
            case PortletRenderer.MODE_SHOW:
                renderShow(pr);
                break;
            case PortletRenderer.MODE_ABOUT:
                renderAbout(pr);
                break;
            case PortletRenderer.MODE_HELP:
                renderHelp(pr);
                break;
            case PortletRenderer.MODE_PREVIEW:
                renderPreview(pr);
                break;
            case PortletRenderer.MODE_SHOW_DETAILS:
                renderShowDetails(pr);
                break;
            case PortletRenderer.MODE_EDIT:
                renderEdit(pr);
                break;
            case PortletRenderer.MODE_EDIT_DEFAULTS:
                renderEditDefaults(pr);
                break;
            case PortletRenderer.MODE_LINK:
                renderLink(pr);
                break;
            default:
                throw new PortletException("Render Mode not supported");
            }
            renderPortletFooter(pr);
        }
        catch (IOException ioe)
        {
            throw new PortletException(ioe);
        }
    }

    /**
     * Renders the contents for the <i>show mode</i>.
     *
     * @param pr a PortletRenderRequest. Note: since this mode may also be
     * displayed by mobile devices, we output content in Mobile XML if this is
     * the preferred content type of the render request.
     */
    public void renderShow(PortletRenderRequest pr) throws IOException
    {
        RenderContext rc = pr.getRenderContext();
        
        // don't generate any content if the portlet is collapsed.
        if (rc.isCollapsed())
        {
            return;
        }
        
        if(pr.getContentType().startsWith(TYPE_MOBILE))
        {
            PrintWriter out = pr.getWriter();
            out.println("<SimpleText><SimpleTextItem>This is the default " +
                        "<em>show</em> mode</SimpleTextItem></SimpleText>");
        }
        else
        {
            PrintWriter out = pr.getWriter();
            out.println("This is the default <i>show</i> mode");
        }
    }

    /**
     * Renders the contents for the <i>about mode</i>.
     *
     * @param pr a PortletRenderRequest.
     */
    public void renderAbout(PortletRenderRequest pr) throws IOException
    {
        PrintWriter out = pr.getWriter();
        out.println("This is the Default <i>about</i> mode");
    }

    /**
     * Renders the contents for the <i>help mode</i>.
     *
     * @param pr a PortletRenderRequest.
     */
    public void renderHelp(PortletRenderRequest pr) throws IOException
    {
        PrintWriter out = pr.getWriter();
        out.println("This is the Default <i>help</i> mode");
    }

    /**
     * Renders the contents for the <i>preview mode</i>.
     *
     * @param pr a PortletRenderRequest.
     */
    public void renderPreview(PortletRenderRequest pr) throws IOException
    {
        PrintWriter out = pr.getWriter();
        out.println("This is the Default <i>preview</i> mode");
    }

    /**
     * Renders the contents for the <i>show details mode</i>.
     *
     * @param pr a PortletRenderRequest.
     */
    public void renderShowDetails(PortletRenderRequest pr)
        throws IOException
    {
        PrintWriter out = pr.getWriter();
        out.println("This is the Default <i>show details</i> mode");
    }

    /**
     * Renders the contents for the <i>edit mode</i>. This mode uses a {@link
     * NameValuePersonalizationObject} in conjunction with {@link
     * FilePersonalizationManager} to support customization of the portlet's
     * title.
     *
     * @param pr a PortletRenderRequest.
     */
    public void renderEdit(PortletRenderRequest pr)
        throws PortletNotFoundException, IOException, AccessControlException
    {
        PrintWriter out = pr.getWriter();
        if (pr.getMode() == PortletRenderer.MODE_EDIT_DEFAULTS)
        {
            out.println("This is the Default <i>edit defaults</i> mode");
            out.println("<p>");
        }
        else
        {
            out.println("This is the Default <i>edit</i> mode");
            out.println("<p>");
        }
        NameValuePersonalizationObject data = (NameValuePersonalizationObject)
            PortletRendererUtil.getEditData(pr);
        out.println("<table BORDER=\"0\" CELLSPACING=0>");
        out.println("<tr><td>Title:</td><td><INPUT TYPE=\"text\" "+
                    "SIZE=\"40\" MAXLENGTH=\"60\" NAME=\"dr_title" +
                    "\" VALUE=\"" + data.getPortletTitle() +
                    "\" /></td></tr></table>");
    }

    /**
     * Renders the contents for the <i>edit defaults mode</i>. This mode uses a
     * {@link NameValuePersonalizationObject} in conjunction with {@link
     * FilePersonalizationManager} to support customization of the portlet's
     * title.
     *
     * @param pr a PortletRenderRequest.
     */
    public void renderEditDefaults(PortletRenderRequest pr)
        throws PortletNotFoundException, IOException, AccessControlException
    {
        renderEdit(pr);
    }

    /**
     * Renders the contents for the <i>link mode</i>. Note, since this mode is
     * generally only used for mobile devices, we output content in Mobile XML
     * if this is the preferred content type of the render request.
     *
     * @param pr a PortletRenderRequest.
     */
    public void renderLink(PortletRenderRequest pr)
        throws IOException, AccessControlException
    {
        String title = PortletRendererUtil.getTitle(pr);
        String url = URLEncoder.encode(pr.getRenderContext().getPageURL());
        if(pr.getContentType().equals(TYPE_MOBILE))
        {
            PrintWriter out = pr.getWriter();
            out.println("<SimpleHref target=\"" + url + "\">" 
                        + title + "</SimpleHref>");
        }
        else
        {
            PrintWriter out = pr.getWriter();
            out.println("<a href=\"" + url + "\">" + 
                        title + "</a>");
        }
    }

    protected void decideContentType(PortletRenderRequest pr)
    {
        String contentType = pr.getPreferredContentType();
        if(contentType == null || !contentType.equals(TYPE_MOBILE))
        {
            contentType = TYPE_HTML;
        }
        pr.setContentType(contentType);
    }

    protected void handleEditData(PortletRenderRequest pr)
        throws PortletNotFoundException, IOException, AccessControlException
    {
        String actionParam = retrieveActionParam(pr);
        String action = pr.getParameter(actionParam);
        NameValuePersonalizationObject data =
            (NameValuePersonalizationObject)PortletRendererUtil.getEditData(pr);
        data.setPortletTitle(pr.getParameter("dr_title"));
        PortletRendererUtil.submitEditData(pr, data);
        if (action.equalsIgnoreCase("OK"))
        {
            HttpPortletRendererUtil.sendRedirect(pr, pr.getRenderContext().getBackURL());
            return;
        } 
        else if (action.equalsIgnoreCase("APPLY")) 
        {
            HttpPortletRendererUtil.sendRedirect(pr, pr.getRenderContext().getPageURL());
            return;
        }
    }

    protected void renderPortletHeader(PortletRenderRequest pr)
        throws AccessControlException, IOException
    {
        if (hasCustomizeAction(pr))
        {
            return;
        }
        PortletRendererUtil.renderPortletHeader(pr, true,
                                                retrieveActionParam(pr));
    }

    protected void renderPortletFooter(PortletRenderRequest pr)
        throws AccessControlException, IOException
    {
        if (hasCustomizeAction(pr))
        {
            return;
        }
        PortletRendererUtil.renderPortletFooter(pr, true);
    }

    private boolean hasCustomizeAction(PortletRenderRequest pr)
    {
        String actionParam = retrieveActionParam(pr);
        String action = pr.getParameter(actionParam);
        if (action != null)
        {
            return true;
        }
        return false;
    }

    private String retrieveActionParam(PortletRenderRequest pr)
    {
        // action parameter will be preset if called from RenderManager
        String actionParam = PortletRendererUtil.getEditFormParameter(pr);
        if (actionParam == null)
        {
            // otherwise set it here
            actionParam = "dr_action";
        }
        return actionParam;
    }

}






