/* ======================================================================
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 org.bodington.servlet.*;
import org.bodington.server.realm.Permission;
import org.bodington.server.resources.*;
import org.bodington.server.*;
import org.bodington.servlet.template.Template;
import org.bodington.util.TextUtils;

import org.apache.log4j.Logger;

import java.rmi.RemoteException;
import java.util.Enumeration;
import java.util.StringTokenizer;
import java.io.*;
import javax.servlet.*;

public class EasyBuilderFacility extends SuiteFacility
{
    private static Logger log = Logger.getLogger(EasyBuilderFacility.class);
    
    protected String getParamValue( Request breq, String paramName, PrintWriter out )
    {
        String value = super.getParamValue(breq, paramName, out);
        if (("url").equals(paramName))
        {
            try
            {
                value = breq.getBuildingSession().findUniqueName(value);
            }
            catch (BuildingServerException e)
            {
            }
        }
        return value;
        
    }
    public void insert( Request req, PrintWriter out, String command, String insertname )
    throws ServletException, IOException
    {
        log.debug( " EasyBuilderFacility insert()" );
        
// TODO check out != null at the start of the method, or before a group of calls which rely on it.
        
        if ( command.equalsIgnoreCase( "update_minimenu" ) )
        {
            printJavaScriptToDisplayMiniMenuFrame(out);
            return;
        }
        
        if ( command.equalsIgnoreCase( "createcontainer" ) )
        {
            if ( req.getParameter("url") != null && out != null) {
                Resource new_resource;
                String container_name, creator, keywords;
                new_resource = createconfirm( req, out, insertname );
                if ( new_resource == null )
                {
                    out.println("Creation of containing resource failed");
                    return;
                }
                
                // createconfirm() might have altered new resource's name, so get/set it here:
                container_name = new_resource.getName();
                
                try {
                    BuildingSession session = BuildingSessionManagerImpl.getSession( new_resource );
        			
                    creator = req.getParameter( "creator" );
                    if (creator != null && creator.length() > 0)
                    {
                        creator = req.getParameter( "creator" );
                        session.updateMetadataAuthorField( creator, "my.email@ox.ac.uk" );
                    }
                    
                    keywords = req.getParameter( "keywords" );
                    extractKeywordsFromString(keywords, session);
                }
                catch (BuildingServerException ex) {
                    out.println("Error adding metadata for resource:" + ex.friendlyMessage());
                }
                
                printJavaScriptToRedirect(out, container_name);
            }
            
            return;
        }
        
        if ( command.equalsIgnoreCase( "createincontainer" ) )
        {
            if ( out!=null )
            {
                Resource new_resource;
                
                new_resource = createconfirm( req, out, insertname );
                
                if ( new_resource == null )
                {
                    return;
                }
                
                printJavaScriptToDisplayMiniMenuFrame(out);
            }
            return;
        }
        
        if (  command.equalsIgnoreCase( "uploadwithlink" ) )
        {
            if ( out!=null )
            {
                String file_name, link, errorMessage;
                Resource new_resource;
                boolean completed;
                
                file_name = req.getParameterFileName("file");
                // TODO Seems to be a bug in Bod code to check that the file exists?
                // (possible to upload a non-existent file...
                if ( file_name == null || file_name.equals( "" ))
                {
                    out.println( "No file name supplied" );
                    return;
                }
                
                new_resource = createconfirm( req, out, insertname );
                if ( new_resource == null )
                {
                    out.println("Creation of the link to the uploaded file has failed.<br />");
                    out.println("File has not been uploaded.");
                    return;
                }
                
                completed = upload( req, out, new_resource, true );
                
                errorMessage = "please use the <a href=\"bs_template_manage.html\">'Manage'<a> interface to correct this.";
                
                if ( !completed )
                {
                    // TODO rollback resource creation if upload fails?
                    out.println( "File upload failed, " + errorMessage );
                    return;
                    //           file_name = "bs_template_manage.html";
                }
                
                // TODO get full URL:
                link = "./" + new_resource.getName() + "/" + file_name;
                
                if ( new_resource instanceof QuickLink)
                {
                    try {
                        QuickLink quickLink = (QuickLink) new_resource;
                        quickLink.setNewWindow(true);
                        QuickLinkFacility.setLink(quickLink, link, req);
                        quickLink.save();
                    }
                    catch (BuildingServerException ex) {
                        out.println("The URL for the link could not be set, " + errorMessage);
                    }
                }
                else
                    out.println("The URL for the link could not be set, " + errorMessage);
                
                printJavaScriptToDisplayMiniMenuFrame(out);
            }
            
            return;
        }
        
        if ( command.equalsIgnoreCase( "shorttitle" ) )
        {
            if ( out != null )
            {
                try
                {
                    String title = req.getResource().getTitle();
                    if ( title != null )
                    {
                        if ( title.length() > 20 )
                            title = title.substring(0, 20) + "...";
                        
                        out.println( title );
                    }
                }
                catch (BuildingServerException e)
                {
                    // do nothing
                }
            }
            
            return;
        }

        if ( command.equalsIgnoreCase( "get_metadata" ) )
        {
            if ( out != null )
            {
                try
                {
                    String[] fields;
                    BuildingSession session = BuildingSessionManagerImpl.getSession( req.getResource() );
                    fields = session.getFieldValuesFromMetadata( insertname );
                    printStringFromArray( fields, out );
                }
                catch (BuildingServerException e)
                {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            
            return;
        }
        
        if ( command.equalsIgnoreCase( "modify" ) )
        {
            try
            {
                BuildingSession  session = BuildingSessionManagerImpl.getSession( req.getResource() );
                String keywords = req.getParameter( "keywords" );
                extractKeywordsFromString( keywords, session );
                super.insert(req, out, command, insertname);
                return;
            }
            catch (BuildingServerException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        
        if ( command.equalsIgnoreCase( "contentlist" ) )
        {
            if ( out != null )
                contentlist( req, out, insertname );
            //           fullResourceMenu(req, out); // new look-and-feel
            
            return;
        }
        
        super.insert( req, out, command, insertname );
    }
    
    
    private void extractKeywordsFromString(String keywords, BuildingSession session) throws RemoteException
    {
        if ( keywords != null )
        {
            StringTokenizer tokens = new StringTokenizer(keywords, ",");
            String[] keywordArray = new String[tokens.countTokens()];
            int n = 0;
            while (tokens.hasMoreTokens())
            {
                keywordArray[n] = tokens.nextToken().trim();
                n++;
            }
            session.updateMetadataKeywords(keywordArray, "en");
        }
    }
    
    private void printStringFromArray( String[] fields, PrintWriter out ) 
    {
        StringBuffer buffer = new StringBuffer();
        
        for ( int i=0; i<fields.length; i++ )
        {
            if( i>0 )
            {
                buffer.append( ", " );
            }
            buffer.append( fields[i] );
        }
        out.print( buffer );
    }


    /**
     * Switches/updates left hand frame to display mini-menu (resource menu of resources in new container).
     * @param out Writer to write JavaScript to browser
     */
    private void printJavaScriptToDisplayMiniMenuFrame(PrintWriter out)
    {
        out.println("<script type=\"text/javascript\">");
        out.println("top.buildmain.graphic.location.href=\"bs_template_minimenu.html\";");
        out.println("</script>");
    }
    
    /**
     * Redirects menu frame to display easybuilder creation menu at container location.
     * @param out Writer to write JavaScript to browser
     * @param containerName Name of (newly-created) resource whose contents are to be displayed in the mini-menu
     */
    private void printJavaScriptToRedirect(PrintWriter out, String containerName)
    {
        out.println("<script type=\"text/javascript\">");
        out.println("top.buildtop.location.href=\""+ containerName +"/bs_template_top.html\";");
        out.println("top.buildmain.menu.location.href=\""+ containerName +"/bs_template_easybuildermenu.html\";");
        out.println("</script>");
    }
    
    /**
     * Resets left hand frame to normal display.
     * (If user presses back button in browser, they could end up with
     *  left hand frame displaying the minimenu when it shouldn't be.)
     * @param out Writer to write JavaScript to browser
     */
    public void printJavaScriptToResetLeftFrame(PrintWriter out)
    {
        out.println("<script type=\"text/javascript\">");
        out.println("top.buildmain.graphic.location.href=\"bs_template_graphic.html\";");
        out.println("</script>");
    }
    
    /**
     * Cut down version of navigation() method in Facility.
     * comment from Facilty class:
     * "this method is only called from legacy templates and we
     * have to assume that the html page class has been given
     * us in an attribuate to the BUILDING tag but we expect
     * the default to be a navigation page."
     */
    
    public void contentlist( Request breq, PrintWriter out, String name )
    throws IOException
    {
        String smliconurl, parentsmliconurl;
        boolean tree;
        int n;
        BuildingContext context;
        FacilityList fl;
        Facility facility;
        Template template;
        String colour_mapper_code="";
        Resource resource, current, next;
//        String html_body_class, tree_attribute;
        String tree_attribute;
        
        context = BuildingContext.getContext();
        fl = FacilityList.getFacilities();
        
//        org.bodington.servlet.HttpSession http_session = (org.bodington.servlet.HttpSession)breq.getSession( false );
//        NavigationSession nav_session = breq.getServerNavigationSession();
        
//        html_body_class = breq.getInsertAttribute( "html_body_class", "bodington_navigation_page" );
        
//        try {
//            StyleSheetSessionData sssd = styleSheet.getStyleSheetSessionData( http_session );
//            ColourPreferenceMapper colour_mapper = sssd.getUserColourPreferenceMapper( http_session );
            
//            BuildingSession session = nav_session.getSession();
//            Color f;
//            Color b;
//            if ("bodington_navigation_page".equals(html_body_class)) {
//                f = session.getPropertyColor(
//                    "style_navigation_graphic_foreground_colour", new Color(0xeeeeee));
//                b = session.getPropertyColor(
//                    "style_navigation_graphic_background_colour", new Color(0x111111));
//            }
//            else {
//                f = session.getPropertyColor("style_graphic_foreground_colour",
//                    new Color(0xeeeeee));
//                b = session.getPropertyColor("style_graphic_background_colour",
//                    new Color(0x111111));
//            }
//            colour_mapper.setReferenceColours(b, f);
//            colour_mapper_code = "?code=" + colour_mapper.toString();
//        }
//        catch (BuildingServerException bsex) {
//            logException(out, "Facility", "navigation",
//                "A technical problem occurred.",
//                bsex);
//            
//            colour_mapper_code = "";
//        }
            
        tree_attribute = (String)breq.getInsertAttribute( "tree", null );
        tree =  tree_attribute == null ||
        tree_attribute.equalsIgnoreCase( "yes" ) ||
        tree_attribute.equalsIgnoreCase( "true" );
        
        try
        {
            resource = context.getResource();
            
            if ( name.equalsIgnoreCase( "links" ) )
            {
                parentsmliconurl = "bs_template_iconsmall.gif";
                template = Template.get( this.facilityname, resource.getImplicitHttpUIStyle(), null, "iconsmall.gif" );
                if ( template != null )
                    parentsmliconurl = breq.getContextPath() + "/processedgif/templates" + template.getUrl() + colour_mapper_code;
                
                Enumeration enumeration=resource.findChildren();
                n=0;
                current=null;
                while ( enumeration.hasMoreElements() )
                {
                    current = (Resource)enumeration.nextElement();
                    if ( current.checkPermission( Permission.SEE ) )
                        break;
                    current=null;
                }
                
                while( current!=null )
                {
                    next=null;
                    while ( enumeration.hasMoreElements() )
                    {
                        next = (Resource)enumeration.nextElement();
                        if ( next.checkPermission( Permission.SEE ) )
                            break;
                        next=null;
                    }
                    
                    // find url of small icon for current resource
                    smliconurl = current.getName() + "/bs_template_navigation_iconsmall.gif";
                    facility = fl.get( new Integer( current.getHttpFacilityNo() ) );
                    if ( facility!=null )
                    {
                        template = Template.get( facility.facilityname, current.getImplicitHttpUIStyle(), null, "iconsmall.gif" );
                        if ( template != null )
                            smliconurl = breq.getContextPath() + "/processedgif/templates" + template.getUrl() + colour_mapper_code;
                    }
                    
                    if ( n==0 )
                    {
                        // if we have found a resource to list start off the table
                        out.print( "<TABLE border=0 cellpadding=0 cellspacing=0>" );
                        if ( tree )
                        {
                            // first display
                            // icon for containing resource
                            out.print( "<TR><TD VALIGN=TOP COLSPAN=2>" );
                            out.print( "<IMG alt=\"" + resource.getResourceTypeName() + ".\" BORDER=0 SRC=\"" );
                            out.print( parentsmliconurl );
                            out.print( "\">" );
                            //out.print( "</TD><TD>" );
                            out.println( "</TD></TR>" );
                            out.println( "<TR><TD VALIGN=TOP BACKGROUND=" + breq.getContextPath() + "/icons/thread-line.gif>" );
                            out.print( "<IMG BORDER=0 SRC=\"" + breq.getContextPath() + "/icons/thread-filler.gif\">" );
                            out.println( "</TD><TD></TD></TR>" );
                        }
                    }
                    n++;
                    
                    out.println( "<TR>" );
                    
                    if ( tree )
                    {
                        if ( next==null )
                            out.println( "<TD VALIGN=TOP>" );
                        else
                            out.println( "<TD VALIGN=TOP BACKGROUND=" + breq.getContextPath() + "/icons/thread-line.gif>" );
                        out.println("<IMG SRC=" + breq.getContextPath() + "/icons/resource-arrow.gif>");
                        out.println( "</TD>" );
                    }
                    
                    out.print( "<TD VALIGN=TOP>" );
                    // <altAndTitle> --->>>
                    out.print( "<IMG alt=\"Icon for " + 
                        (TextUtils.beginsWithVowel(current.getResourceTypeName()) ? "an" : "a") 
                        + " " + current.getResourceType() + ".\" CLASS=bs-links-icon BORDER=0 SRC=\"" );
                    // <<<--- <altAndTitle>	
                    out.print( smliconurl );
                    out.print( "\">" );
                    out.println( "</TD>" );
                    
                    out.print( "<TD VALIGN=TOP>" );
                    out.print( "<SPAN CLASS=bs-links-title>" );
                    out.print( current.getTitle() );
                    //out.println( "</NOBR>" );
                    out.println( "</SPAN>" );
                    out.println( "</TD>" );
                    
                    out.println( "</TR>" );
                    
                    current = next;
                }
                if ( n>0 )
                    out.println( "</TABLE>" );
                return;
            }
        }
        
        catch ( BuildingServerException bsex )
        {
            return;
        }
        
        out.print( "<! navigation HTML inserted here>" );
    }    
}