/*
 * The contents of this file are subject to the terms 
 * of the Common Development and Distribution License 
 * (the License).  You may not use this file except in
 * compliance with the License.
 * 
 * You can obtain a copy of the license at 
 * https://glassfish.dev.java.net/public/CDDLv1.0.html or
 * glassfish/bootstrap/legal/CDDLv1.0.txt.
 * See the License for the specific language governing 
 * permissions and limitations under the License.
 * 
 * When distributing Covered Code, include this CDDL 
 * Header Notice in each file and include the License file 
 * at glassfish/bootstrap/legal/CDDLv1.0.txt.  
 * If applicable, add the following below the CDDL Header, 
 * with the fields enclosed by brackets [] replaced by
 * you own identifying information: 
 * "Portions Copyrighted [year] [name of copyright owner]"
 * 
 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
 */

package com.sun.enterprise.tools.guiframework.view;

import com.iplanet.jato.RequestContext;
import com.iplanet.jato.SecurityCheckException;
import com.iplanet.jato.command.Command;
import com.iplanet.jato.command.CommandEvent;
import com.iplanet.jato.command.CommandException;
import com.iplanet.jato.model.ModelControlException;
import com.iplanet.jato.view.View;
import com.iplanet.jato.view.ViewBean;
import com.iplanet.jato.view.ViewBeanBase;
import com.iplanet.jato.view.event.ChildContentDisplayEvent;
import com.iplanet.jato.view.event.ChildDisplayEvent;
import com.iplanet.jato.view.event.DisplayEvent;

import java.util.EventObject;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.sun.enterprise.tools.guiframework.event.descriptors.EventDescriptor;
import com.sun.enterprise.tools.guiframework.exception.FrameworkError;
import com.sun.enterprise.tools.guiframework.exception.FrameworkException;
import com.sun.enterprise.tools.guiframework.util.LogUtil;
import com.sun.enterprise.tools.guiframework.view.descriptors.ViewDescriptor;


/**
 *  This is the base ViewBean class that provides Descriptor support.  This
 *  class may often be used directly, or extended.  This class changes the
 *  default event handling mechanism in JATO to one where the events (such as
 *  beginDisplay or begin&lt;child&gt;Display) are handled by declared handlers.
 */
public class DescriptorViewBeanBase extends ViewBeanBase implements Command, DescriptorContainerView {

    /**
     *	Constructor for creating a new ViewBean.  The desired ViewBean should
     *	be referenced by name.  This name is used to look up the configuration
     *	information for the ViewBean and construct it.
     *
     *	@param context	The RequestContext
     *	@param pageName	The ViewBean name to create
     */
    public DescriptorViewBeanBase(RequestContext context, String pageName, ViewDescriptor desc) {
	super(pageName);

	// Invoke these two methods first b/c other methods depend on these
	setRequestContext(context);
	setLocale(context.getRequest().getLocale());

	setDescriptor(desc);
	registerViewDescriptorChildren();
    }


    /**
     *	This method retrieves this ViewBean's ViewDescriptor.
     *
     *	@return This ViewBean's ViewDescriptor.
     */
    public ViewDescriptor getViewDescriptor() {
	return _viewDesc;
    }


    /**
     *	This method sets the ViewDescriptor for this ViewBean.
     */
    public void setDescriptor(ViewDescriptor desc) {
	if (desc == null) {
	    throw new FrameworkException("Cannot set null ViewDescriptor!",
	    desc, this);
	}

	// Set the Default Display URL
	String url = desc.getDisplayURL();

	// Tracing message...
	if (LogUtil.isLoggable(LogUtil.FINER)) {
	    LogUtil.log(LogUtil.FINER, "trace.setDisplayURL", url);
	}

	if (url == null) {
	    throw new FrameworkException(
		"DisplayURL in ViewDescriptor cannot be NULL for ViewBeans!",
		desc, this);
	}
	setDefaultDisplayURL(getLocalizedURL(url));

	// Save the Descriptor for use later
	_viewDesc = desc;
    }



    //////////////////////////////////////////////////////////////////////
    //              Child Registration / Creation Methods               //
    //////////////////////////////////////////////////////////////////////

    /**
     *	<P>This invokes getViewDescriptor().registerChildren(this) to provide a
     *	place to register children.  The reason the Descriptors are involved is
     *	because some children may be Views which in turn have CommandField's.
     *	However, these Views may not be RequestHandling Views.  Because of
     *	this, they do not get a chance to register their own children and thus
     *	get a chance to handle the request.</P>
     */
    public void registerViewDescriptorChildren() {
	DescriptorViewHelper.registerViewDescriptorChildren(getViewDescriptor(), this);
    }


    /**
     *
     */
    public View createChild(String name) {
	return DescriptorViewHelper.createChild(this, name);
    }



    //////////////////////////////////////////////////////////////////////
    //                          Event Methods                           //
    //////////////////////////////////////////////////////////////////////

    /**
     *	This method dispatches BeginDisplay events to each registered
     *	BeginDisplay event handler according the the ViewDescriptor.
     *
     *	@param event	The DisplayEvent, created internally by JATO
     */
    public void beginDisplay(DisplayEvent event) throws ModelControlException {
	DescriptorViewHelper.beginDisplay(this, event);
	super.beginDisplay(event);
    }


    /**
     *
     */
    public boolean beginChildDisplay(ChildDisplayEvent event) throws ModelControlException {
    	return DescriptorViewHelper.beginChildDisplay(this, event);
    }


    /**
     *
     */
    public String endChildDisplay(ChildContentDisplayEvent event) throws ModelControlException {
	return DescriptorViewHelper.endChildDisplay(this, event);
    }


    /**
     *	We should check to make sure the user is authenticated here.
     */
    public void securityCheck() throws SecurityCheckException {
	// Do nothing for now
	super.securityCheck();
    }


    public void endDisplay(DisplayEvent event) {
	DescriptorViewHelper.endDisplay(this, event);
	super.endDisplay(event);
    }


    //////////////////////////////////////////////////////////////////////
    //                         Command Methods                          //
    //////////////////////////////////////////////////////////////////////

    /**
     *	This method is invoked to dispatch all requests to the appropriate
     *	place.
     *
     *	@param event	The command event, contains information pertinent to
     *			to the invocation of this command
     *
     *	@throws CommandException	Thrown if an error occurs executing
     *					the command
     */
    public void execute(CommandEvent event) throws CommandException {
	DescriptorViewHelper.execute(
	    getRequestContext(), (View)event.getSource(), event);
    }


    /**
     *	This is a convenience method to obtain a ViewBean by name.  The
     *	ViewBeanManager will be used.
     *
     *	@param	viewBeanName	The ViewBean name to use.
     */
    public ViewBean getViewBean(String viewBeanName) {
	ViewBean viewBean = null;
	try {
	    viewBean = getRequestContext().getViewBeanManager().
		getViewBean(viewBeanName);
	} catch (ClassNotFoundException ex) {
	    throw new RuntimeException("Unable to forward to: '"+viewBeanName+
		"', cannot find that ViewBean!", ex);
	}
	return viewBean;
    }



    //////////////////////////////////////////////////////////////////////
    //                   IDescriptorViewBean Methods                    //
    //////////////////////////////////////////////////////////////////////

    /**
     *	This method is needed from IndexTreeView.
     */
    public void setAttributes(Map attributes) {
	_attributes = attributes;
    }
    

    /**
     *	This method is needed from IndexTreeView.
     */
    protected Object getAttribute(String name) {
	return (_attributes == null) ? null : _attributes.get(name);
    }


    /**
     *	This method returns the user's perferred locale.
     *
     *	@return The user's locale (if available, default otherwise)
     */
    public Locale getLocale() {
	return _locale;
    }


    /**
     *	This method allows you to overwrite the user's locale, which by
     *	default, is obtained via the ServletRequest.getLocale().
     *
     *	@param	locale	The Locale to use
     */
    public void setLocale(Locale locale) {
	_locale = locale;
    }


    //////////////////////////////////////////////////////////////////////
    //                         Utility Methods                          //
    //////////////////////////////////////////////////////////////////////

    public String getLocalizedURL(String fileName) {
	if (getLocale().equals(Locale.ENGLISH) || getLocale().getLanguage().equals("en")) {
	    return fileName;
	}

	int index = fileName.indexOf('?');
	String newName = null;

	if(index != -1) {
	    newName = fileName.substring(0, index);
	} else {
	    newName = fileName;
	}
	int lastdot = newName.lastIndexOf(".jsp");
	newName = newName.substring(0,lastdot) + "_" + getLocale().getLanguage() + ".jsp";

	try {
	    DescriptorViewHelper.verifyClassExists(getRequestContext().getServletContext(), newName);
	    if(index >= 0) {
		newName += fileName.substring(fileName.indexOf('?'));
	    }
	} catch (ClassNotFoundException ex) {
	    // don't return a localized version, use the given version
	    return fileName;
	}
	return newName;
    }

    private Locale _locale = null;

    private ViewDescriptor _viewDesc = null;
    private Map _attributes = null;
}
