/*
 * ======================================================================
 * The Bodington System Software License, Version 1.0 Copyright (c) 2001
 * The University of Leeds. 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 acknowledgement: "This product includes software developed by
 * the University of Leeds (http://www.bodington.org/)." Alternately, this
 * acknowledgement may appear in the software itself, if and wherever such
 * third-party acknowledgements normally appear. 4. The names "Bodington",
 * "Nathan Bodington", "Bodington System", "Bodington Open Source Project", and
 * "The University of Leeds" must not be used to endorse or promote products
 * derived from this software without prior written permission. For written
 * permission, please contact d.gardner@leeds.ac.uk. 5. The name "Bodington" may
 * not appear in the name of products derived from this software without prior
 * written permission of the University of Leeds. THIS SOFTWARE IS PROVIDED ``AS
 * IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * TITLE, THE IMPLIED WARRANTIES OF QUALITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OF LEEDS 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 was
 * originally created by the University of Leeds and may contain voluntary
 * contributions from others. For more information on the Bodington Open Source
 * Project, please see http://bodington.org/
 * ======================================================================
 */

package org.bodington.servlet.facilities;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;

import org.apache.log4j.Logger;
import org.bodington.server.BuildingServerException;
import org.bodington.server.realm.Permission;
import org.bodington.server.resources.ImageBlockResource;
import org.bodington.server.resources.Resource;
import org.bodington.servlet.Request;

/**
 * Class to handle the web interface to Image Block resources.
 * @author Colin Tatham
 */

public class ImageBlockFacility extends Facility
{
    private static Logger log = Logger.getLogger(ImageBlockFacility.class);

    public Resource newResource()
    {
        return new ImageBlockResource();
    }
    
    public boolean canCopy( Resource resource )
    {
        return true;
    }
    
    public boolean initResource( Request breq, Resource new_resource )
    throws Exception
    {
        ImageBlockResource imageblock;
        
        if ( !(new_resource instanceof ImageBlockResource) )
            throw new Exception( "Technical problem: An incorrect type of resource was created." );
        
        imageblock = (ImageBlockResource)new_resource;
        
        String sourceURL, linkHREF, altTagText, imageHeight, imageWidth;
        boolean displayTitle, displayDescription;
        
        if ( breq.getParameter( "sourceURL" ) == null )
        {
            throw new Exception( "No source URL specified." );
        }
        sourceURL = breq.getParameter( "sourceURL" );
        imageblock.setSourceURL( sourceURL );
        
        displayTitle = breq.getParameter( "displayTitle" ) != null;
        imageblock.setDisplayTitle( displayTitle );
        
        displayDescription = breq.getParameter( "displayDescription" ) != null;
        imageblock.setDisplayDescription( displayDescription );
        
        // remaining properties don't need check for null:
        
        altTagText = breq.getParameter( "altTagText" ); 
        imageblock.setAltTagText( altTagText );
         
        linkHREF = breq.getParameter( "linkHREF" );
        imageblock.setLinkHREF( linkHREF );
        
        imageHeight = breq.getParameter( "imageHeight" );
        imageblock.setImageHeight( imageHeight );
        
        imageWidth = breq.getParameter( "imageWidth" );
        imageblock.setImageWidth( imageWidth );
        
        return true;
    }
    
    public boolean initResource( Resource original_resource, Resource new_resource )
    throws BuildingServerException
    {
        if ( !(new_resource instanceof ImageBlockResource) )
            throw new BuildingServerException(
                "Error: The wrong type of resource was created." );

        ImageBlockResource original = (ImageBlockResource)original_resource;
        ImageBlockResource imageblock = (ImageBlockResource)new_resource;

        // sets isDisplayTitle() and isDisplayDescription():
        imageblock.setImageBlockFlags( original.getImageBlockFlags() );
        
        imageblock.setSourceURL( original.getSourceURL() );
        imageblock.setAltTagText( original.getAltTagText() );
        imageblock.setLinkHREF( original.getLinkHREF() );
        imageblock.setImageHeight( original.getImageHeight() );
        imageblock.setImageWidth( original.getImageWidth() );

        return true;
    }

    public void insert(Request req, PrintWriter out, String command, String insertname)
    throws ServletException, IOException
        {
        log.debug(" ImageBlockFacility insert()");
        
        if (!(req.getResource() instanceof ImageBlockResource))
        {
            String message = "Wrong type of resource found, expecting ImageBlock resource";
            log.error(message);
            return;
        }
        
        ImageBlockResource imageblock = (ImageBlockResource) req.getResource();
        
        if (command.equalsIgnoreCase("modifyproperties"))
        {
            if (req.getParameter("savesettings") != null)
            {
                // Save button has been pushed...   
                updateDisplayTitle(req, imageblock);
                updateDisplayDescription(req, imageblock);
                updateSourceURL(req, imageblock);
                updateAltTagText(req, imageblock);
                updateImageHeight(req, imageblock);
                updateImageWidth(req, imageblock);
                updateLinkHREF(req, imageblock);
                
                if (imageblock.isUnsaved())
                {
                    try
                    {
                        imageblock.save();
                    }
                    catch (BuildingServerException e)
                    {
                        log.debug( "Error updating ImageBlock resource.", e );
                    }
                }
                out.println("Settings saved.");
            }
            return;
        }
        
        if (command.equalsIgnoreCase("value"))
        {
            displayCurrentSettings(insertname, imageblock, out);
            return;
        }
        
        super.insert(req, out, command, insertname);
        }

    /** Checks the current value of the property specified, and displays it in the requesting page.
     * Used by resource modification page.
     * @param insertname The name of the property to query.
     * @param imageblock The resource whose properties are to be queried.
     * @param out Writer to write property value to browser.
     * @return Boolean confirming that the command was acted upon.
     */
    private boolean displayCurrentSettings(String insertname, ImageBlockResource imageblock, PrintWriter out)
    {
        // returns true if command was acted upon.
        if (insertname.equalsIgnoreCase("displayTitle"))
        {
            if (imageblock.isDisplayTitle()) out.print("checked");
            return true;
        }
        
        if (insertname.equalsIgnoreCase("displayDescription"))
        {
            if (imageblock.isDisplayDescription()) out.print("checked");
            return true;
        }
        
        if (insertname.equalsIgnoreCase("sourceURL"))
        {
            out.print(imageblock.getSourceURL());
            return true;
        }
        
        if (insertname.equalsIgnoreCase("altTagText"))
        {
            out.print(imageblock.getAltTagText());
            return true;
        }
        
        if (insertname.equalsIgnoreCase("imageHeight"))
        {
            if (imageblock.getImageHeight() != null)
            {
                out.print(imageblock.getImageHeight());
            }
            return true;
        }
        
        if (insertname.equalsIgnoreCase("imageWidth"))
        {
            if (imageblock.getImageWidth() != null)
            {
                out.print(imageblock.getImageWidth());
            }
            return true;
        }
        
        if (insertname.equalsIgnoreCase("linkHREF"))
        {
            if (imageblock.getLinkHREF() != null)
            {
                out.print(imageblock.getLinkHREF());
            }
            return true;
        }
        
        return false;
    }
    
    /** Updates setting which determines whether or not to display a title.
     * (Checks current setting first to avoid unecessary resource saving.)
     * @param req The incoming request.
     * @param imageblock The ImageBlock resource to modify.
     */
    private void updateDisplayTitle(Request req, ImageBlockResource imageblock)
    {
        if (req.getParameter("displayTitle") != null && !imageblock.isDisplayTitle())
        {
            imageblock.setDisplayTitle(true);
            imageblock.setUnsaved();
        }
        else if (req.getParameter("displayTitle") == null && imageblock.isDisplayTitle())
        {
            imageblock.setDisplayTitle(false);
            imageblock.setUnsaved();
        }
    }

    /** Updates setting which determines whether or not to display a description.
     * (Checks current setting first to avoid unecessary resource saving.)
     * @param req The incoming request.
     * @param imageblock The ImageBlock resource to modify.
     */
    private void updateDisplayDescription(Request req, ImageBlockResource imageblock)
    {
        if (req.getParameter("displayDescription") != null && !imageblock.isDisplayDescription())
        {
            imageblock.setDisplayDescription(true);
            imageblock.setUnsaved();
        }
        else if (req.getParameter("displayDescription") == null && imageblock.isDisplayDescription())
        {
            imageblock.setDisplayDescription(false);
            imageblock.setUnsaved();
        }
    }
    
    /** Updates the source URL of the image.
     * (Checks current setting first to avoid unecessary resource saving.)
     * @param req The incoming request.
     * @param imageblock The ImageBlock resource to modify.
     */
    private void updateSourceURL(Request req, ImageBlockResource imageblock)
    {
        if ( !req.getParameter("sourceURL").equals(imageblock.getSourceURL()) )
        {
            imageblock.setSourceURL(req.getParameter("sourceURL"));
            imageblock.setUnsaved();
        }
    }
    
    /** Updates the text to be used in the 'alt' attribute of the HTML image tag.
     * (Checks current setting first to avoid unecessary resource saving.)
     * @param req The incoming request.
     * @param imageblock The ImageBlock resource to modify.
     */
    private void updateAltTagText(Request req, ImageBlockResource imageblock)
    {
        if ( !req.getParameter("altTagText").equals(imageblock.getAltTagText()) )
        {
            imageblock.setAltTagText(req.getParameter("altTagText"));
            imageblock.setUnsaved();
        }
    }
    
    /** Updates the value to be used in the 'height' attribute of the HTML image tag.
     * (Checks current setting first to avoid unecessary resource saving.)
     * @param req The incoming request.
     * @param imageblock The ImageBlock resource to modify.
     */
    private void updateImageHeight(Request req, ImageBlockResource imageblock)
    {
        if ( !req.getParameter("imageHeight").equals(imageblock.getImageHeight()) )
        {
            imageblock.setImageHeight(req.getParameter("imageHeight"));
            imageblock.setUnsaved();
        }
    }
    
    /** Updates the value of the 'width' attribute of the HTML image tag.
     * (Checks current setting first to avoid unecessary resource saving.)
     * @param req The incoming request.
     * @param imageblock The ImageBlock resource to modify.
     */
    private void updateImageWidth(Request req, ImageBlockResource imageblock)
    {
        if ( !req.getParameter("imageWidth").equals(imageblock.getImageWidth()) )
        {
            imageblock.setImageWidth(req.getParameter("imageWidth"));
            imageblock.setUnsaved();
        }
    }
    
    /** Updates the URL to be linked to if the image is to act as a link.
     * (Checks current setting first to avoid unecessary resource saving.)
     * @param req The incoming request.
     * @param imageblock The ImageBlock resource to modify.
     */
    private void updateLinkHREF(Request req, ImageBlockResource imageblock)
    {
        if ( !req.getParameter("linkHREF").equals(imageblock.getLinkHREF()) )
        {
            imageblock.setLinkHREF(req.getParameter("linkHREF"));
            imageblock.setUnsaved();
        }
    }
    
    protected void resourceMenuItem(Resource resource, Request breq,
        PrintWriter out, ResourceMenuOutputState state, int depth, int highlight)
        throws IOException, BuildingServerException
    {
        String title, resource_href, target;
        String description;
        boolean manage;

        ImageBlockResource imageblock = (ImageBlockResource)resource;

        manage = resource.checkPermission(Permission.MANAGE);

        resource_href = (!state.rootless && depth == 1) ? null : (breq.getContextPath()
            + breq.getServletPath() + resource.getFullName());

        target = "_top";

        // heading level for title line matches depth but there are only
        // six heading levels in HTML so stop there.
        int hlevel = (depth > 6) ? 6 : depth;
        int level = ((depth - 1) % 10) + 1;

        // title in heading with appropriate class attribute
        out.print("          <h");
        out.print(hlevel);

        /* TODO:
         *  - Create CSS class for imageblock display?.
         */
        out.print(" class=\"" + state.css_class_prefix
            + "_heading_node_title\">");

        if ( imageblock.isDisplayTitle() )
        {
            title = imageblock.getTitle();
            out.print("<strong>");
            out.print(title);
            out.print("</strong>");
        }

        if (resource_href != null && manage)
        {
            out.print("&nbsp;<a");
            if (target != null)
            {
                out.print(" target=\"");
                out.print(target);
                out.print("\"");
            }
            out.print(" href=\"");
            out.print(resource_href);
            out.print("\" title=\"Manage Image.\"><span style=\"font-size: x-small\"><sup>Manage</sup></span></a>");
        }
        
        out.print("</h"); // end of node_title
        out.print(hlevel);
        out.println(">");

        out.print("<div class=\"" + state.css_class_prefix + "_node_content");

        if (depth == 1)
        {// was commented out in orig code??
            out.print("_without_stalk");
        }
        out.print("_lev");
        out.print(level);
        out.print("_hl");
        out.print(highlight);
        out.print("\">");
        
        // image display code
        // output anchor tag if image is to be a link:
        if (imageblock.isLink())
        {
            out.print("<a href=\"");
            out.print( imageblock.getLinkHREF() );
            out.print("\"");
            out.print(">");
        }
        // image tag:
        out.print("<img src=\"");
        out.print( imageblock.getSourceURL() );
        out.print("\" alt=\"");
        out.print( imageblock.getAltTagText() );
        out.print("\"");
        
        if ( imageblock.getImageHeight() != null )
        {
            out.print(" height=\"");
            out.print( imageblock.getImageHeight() );
            out.print("\"");
        }
        
        if ( imageblock.getImageWidth() != null )
        {
            out.print(" width=\"");
            out.print( imageblock.getImageWidth() );
            out.print("\"");
        }
        
        out.print(" />");
        
        // close anchor tag:
        if (imageblock.isLink())
        {
            out.print("</a>");
        }
        
        if ( imageblock.isDisplayDescription() )
        {
            out.print("<br />");
            description = imageblock.getDescription(); // could return null...
            out.print(description);
        }
        
        String markup = timedResourceText(resource);
        if (markup != null)
            out.print("<div>" + markup + "</div>");

        out.print("</div>");
        out.print( "<div class=\"clearer\">&nbsp;</div>\n");
    }
}