/*
 * 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.admingui.handlers;

import java.util.ArrayList;
import java.util.EventObject;
import java.util.StringTokenizer;

import com.iplanet.jato.view.View;
import com.iplanet.jato.RequestContext;
import com.iplanet.jato.RequestManager;
import com.iplanet.jato.model.Model;

import javax.management.AttributeList;
import javax.management.Attribute;

import com.sun.enterprise.tools.admingui.util.MBeanUtil;
import com.sun.enterprise.tools.admingui.util.Util;

import com.sun.enterprise.tools.guiframework.exception.FrameworkException;
import com.sun.enterprise.tools.guiframework.view.DescriptorCCPageTitle;
import com.sun.enterprise.tools.guiframework.view.DescriptorContainerView;
import com.sun.enterprise.tools.guiframework.view.HandlerContext;
import com.sun.enterprise.tools.guiframework.view.descriptors.ViewDescriptor;


public class SecurityMapHandlers {

    public void createSecurityMap(RequestContext ctx, HandlerContext handlerCtx) {
	View view = handlerCtx.getView();
        if (!(view instanceof DescriptorContainerView)) {
            View parent = view.getParent();
            if (!(parent instanceof DescriptorContainerView)) {
                throw new FrameworkException(
		    "view is not DescriptorContainerView", null, view);
            }  else {
                view = parent;
            }
        }
        if (view instanceof DescriptorCCPageTitle) {
            view = view.getParent();
        }
        DescriptorContainerView descView = (DescriptorContainerView)view;
        ArrayList displayNames = (ArrayList)handlerCtx.getInputValue(DISPLAY_NAMES);
        ArrayList modelNames = (ArrayList)handlerCtx.getInputValue(MODEL_NAMES);
        String objectName = (String)handlerCtx.getInputValue(OBJECT_NAME);
        String methodName = (String)handlerCtx.getInputValue(METHOD_NAME);
        String username = (String)handlerCtx.getInputValue(DISPLAY_USERNAME);
        String password = (String)handlerCtx.getInputValue(DISPLAY_PASSWORD);

        if (displayNames == null)
            throw new FrameworkException("DisplayNames not specified", descView.getViewDescriptor(), view);

        if (modelNames == null)
            throw new FrameworkException("ModelNames not specified", descView.getViewDescriptor(), view);

        if (objectName == null)
            throw new FrameworkException("objectName not specified", descView.getViewDescriptor(), view);

        if (methodName == null)
            throw new FrameworkException("methodName not specified", descView.getViewDescriptor(), view);

        if (username == null)
            throw new FrameworkException("username not specified", descView.getViewDescriptor(), view);

        if (password == null)
            throw new FrameworkException("password not specified", descView.getViewDescriptor(), view);

        AttributeList attrList = new AttributeList();
        Attribute attr;
        for (int i = 0; i < displayNames.size(); i++) {
            String value = (String)descView.getDisplayFieldValue(((String)(displayNames.get(i))));
            String[] str = null;
            String modelName = (String)modelNames.get(i);
            if (modelName.equals(MODEL_PRINCIPAL) || modelName.equals(MODEL_GROUP)) {
                if (Util.isEmpty(value))  //only put in either user group or principal  (anissa)
                        continue;
                if (value != null) 
                    value = value.replaceAll(" ", "");
                if (value != null && value.indexOf(",") != -1) {
                    str = getStringArray(value, ",");
                } else {
                    str = new String[1];
                    str[0] = value;
                }
            }
            if (str != null) {
                attr = new Attribute(modelName, str);
            } else {
                attr = new Attribute(modelName, value);
            }
            attrList.add(attr);
        }
        Object params[] = {attrList, username, password, null};
        String types[] = {
            "javax.management.AttributeList",
            "java.lang.String",
            "java.lang.String",
            "java.lang.String"
        };

        Object returnValue = null;
        try {
            returnValue = MBeanUtil.invoke(objectName, methodName, params, types);
        } catch (Exception ex) {
	    throw new FrameworkException(
		ex, descView.getViewDescriptor(), view);
        }
    }

    public void populateSMDisplayFields(RequestContext ctx, HandlerContext handlerCtx) {
	View view = handlerCtx.getView();
        if (!(view instanceof DescriptorContainerView)) {
            View parent = view.getParent();
            if (!(parent instanceof DescriptorContainerView)) {
                throw new FrameworkException(
		    "view is not DescriptorContainerView", null, view);
            } else {
                view = parent;
            }
        }
        if (view instanceof DescriptorCCPageTitle) {
            view = view.getParent();
        }
        DescriptorContainerView descView = (DescriptorContainerView)view;
        String objectName   = (String)handlerCtx.getInputValue(OBJECT_NAME);
        String methodName   = (String)handlerCtx.getInputValue(METHOD_NAME);
        String mapName   = (String)handlerCtx.getInputValue(MAP_NAME);
        String poolName   = (String)handlerCtx.getInputValue(POOL_NAME);
        if (objectName == null) {
            throw new FrameworkException("Object Name not specified", descView.getViewDescriptor(), view);
	}
        if (methodName == null) {
            throw new FrameworkException("Method Name not specified", descView.getViewDescriptor(), view);
	}
        if (mapName == null) {
            throw new FrameworkException("Map Name not specified", descView.getViewDescriptor(), view);
	}
        if (poolName == null) {
            throw new FrameworkException("poolName not specified", descView.getViewDescriptor(), view);
	}

        String principalNames = null;
        String userNames = null;
        Object params[] = {mapName, poolName};
        String types[] = {
            "java.lang.String",
            "java.lang.String"
        };

        String poolname = null;
        String mapname = null;
        String userName = null;
        String password = null;
        String principals[] = null;
        String usergroups[] = null;

        try {
            Object obj = MBeanUtil.invoke(objectName, GET_ATTRIBUTES_METHOD, params, types);
            AttributeList attrList = (AttributeList)obj;
            if(attrList != null){
                int s = attrList.size();

                for(int i=0;i<s;i++){
                    Attribute attribute =(Attribute)attrList.get(i);
                    if(attribute.getName().equals(MODEL_NAME)){
                        mapname =(String)attribute.getValue();
                        continue;
                    }
                    if ((attribute.getName().equals(MODEL_PRINCIPAL)))
                        principals = (String[])attribute.getValue();
                    if ((attribute.getName().equals(MODEL_GROUP)))
                        usergroups =(String[])attribute.getValue();
                    if((attribute.getName()).equals(MODEL_USERNAME))
                        userName = (String)attribute.getValue();
                    if((attribute.getName()).equals(MODEL_PASSWORD))
                        password = (String)attribute.getValue();

                }

                //ctx.getRequest().getSession().setAttribute(SESSION_GROUPS, usergroups);
                //ctx.getRequest().getSession().setAttribute(SESSION_PRINCIPALS, principals);

                principalNames = getString(principals);
                userNames = getString(usergroups);

                descView.setDisplayFieldValue(DIPSLAY_NAME, mapname);
                descView.setDisplayFieldValue(DISPLAY_PRINCIPAL, principalNames);
                descView.setDisplayFieldValue(DISPLAY_PRINCIPAL_ORIG, principalNames);
                descView.setDisplayFieldValue(DISPLAY_GROUP, userNames);
                descView.setDisplayFieldValue(DISPLAY_GROUP_ORIG, userNames);
                descView.setDisplayFieldValue(DISPLAY_USERNAME, userName);
                descView.setDisplayFieldValue(DISPLAY_PASSWORD, password);
            }
        } catch (Exception ex) {
            throw new FrameworkException(
		"failed while getting attribute names and values", ex,
		descView.getViewDescriptor(), view);
        }
    }

    public void updateSecurityMap(RequestContext ctx, HandlerContext handlerCtx) {
	View view = handlerCtx.getView();
        if (!(view instanceof DescriptorContainerView)) {
            View parent = view.getParent();
            if (!(parent instanceof DescriptorContainerView)) {
                throw new FrameworkException(
		    "view is not DescriptorContainerView", null, view);
            } else {
                view = parent;
            }
        }
        if (view instanceof DescriptorCCPageTitle) {
            view = view.getParent();
        }

        DescriptorContainerView descView = (DescriptorContainerView)view;

        ArrayList displayNames = (ArrayList)handlerCtx.getInputValue(DISPLAY_NAMES);
        ArrayList modelNames = (ArrayList)handlerCtx.getInputValue(MODEL_NAMES);
        String objectName   = (String)handlerCtx.getInputValue(OBJECT_NAME);
        String poolName   = (String)handlerCtx.getInputValue(POOL_NAME);
        
        //String groupListOrig[] = (String[])ctx.getRequest().getSession().getAttribute(SESSION_GROUPS);
        //String principalListOrig[] = (String[])ctx.getRequest().getSession().getAttribute(SESSION_PRINCIPALS);

        String mapName = (String)descView.getDisplayFieldValue(DIPSLAY_NAME);
        String pswd = (String)descView.getDisplayFieldValue(DISPLAY_PASSWORD);
        String username = (String)descView.getDisplayFieldValue(DISPLAY_USERNAME);
        String groupList = (String)descView.getDisplayFieldValue(DISPLAY_GROUP);
        String groupListHidden = (String)descView.getDisplayFieldValue(DISPLAY_GROUP_ORIG);
        String principalList = (String)descView.getDisplayFieldValue(DISPLAY_PRINCIPAL);
        String principalListHidden = (String)descView.getDisplayFieldValue(DISPLAY_PRINCIPAL_ORIG);

        if (objectName == null) {
            throw new FrameworkException("Object Name not specified",
		descView.getViewDescriptor(), view);
	}
        if (poolName == null) {
            throw new FrameworkException("Pool Name not specified",
		descView.getViewDescriptor(), view);
	}
        if (displayNames == null) {
            throw new FrameworkException("Display names not specified",
		descView.getViewDescriptor(), view);
	}
        if (modelNames == null) {
            throw new FrameworkException("Model names not specified",
		descView.getViewDescriptor(), view);
	}

        String[] groups = getStringArray(groupList, ",");
        String[] principals = getStringArray(principalList, ",");
        String groupListOrig[] = getStringArray(groupListHidden, ",");
        String principalListOrig[] = getStringArray(principalListHidden, ",");

        String groupRemoves = getRemoves(groupListOrig, groups);
        String groupAdds = getAdds(groups, groupListOrig);
        String principalRemoves = getRemoves(principalListOrig, principals);
        String principalAdds = getAdds(principals, principalListOrig);

        AttributeList attrList = new AttributeList();
        Attribute attr;
        attr = new Attribute(MODEL_POOLNAME, poolName);
        attrList.add(attr);
        attr = new Attribute(MODEL_NAME, mapName);
        attrList.add(attr);
        attr = new Attribute(MODEL_USERNAME, username);
        attrList.add(attr);
        attr = new Attribute(MODEL_PASSWORD, pswd);
        attrList.add(attr);
        attr = new Attribute(MODEL_ADD_PRINCIPALS, principalAdds);
        attrList.add(attr);
        attr = new Attribute(MODEL_ADD_GROUPS, groupAdds);
        attrList.add(attr);
        attr = new Attribute(MODEL_REMOVE_PRINCIPALS, principalRemoves);
        attrList.add(attr);
        attr = new Attribute(MODEL_REMOVE_GROUPS, groupRemoves);
        attrList.add(attr);
        Object params[] = {attrList, null};
        String types[] = {
            "javax.management.AttributeList",
            "java.lang.String"
        };

        try {
            Object object = MBeanUtil.invoke(objectName, UPDATE_ATTRIBUTES_METHOD, params, types);
        } catch (Exception ex) {
            throw new FrameworkException(ex, descView.getViewDescriptor(), view);
        }
    }

    public String getRemoves(String[] orig, String[] updates) {
        String removes = null;
        if (orig != null && updates != null) {
            for (int i=0; i < orig.length ; i++) {
                boolean match = false;
                for (int j=0; j < updates.length; j++) {
                    if(updates[j].equals(orig[i])){
                        match = true;
                    }
                }
                if (!match) {
                    if (removes == null) {
                        removes = orig[i];
                    } else {
                        removes += ","+orig[i];
                    }
                }
            }
        }

        return removes;
    }

    public String getAdds(String[] updates, String[] orig) {
        String adds = null;
        if(orig != null && updates != null){
            for(int i=0; i < updates.length ; i++) {
                boolean match = false;
                for (int j=0; j < orig.length; j++) {
                    if(orig[j].equals(updates[i])){
                        match = true;
                    }

                }
                if(!match) {
                    if(adds == null) {
                        adds = updates[i];
                    } else {
                        adds += ","+updates[i];
                    }
                }

            }
        }
        return adds;
    }

    private String[] getStringArray(String str, String delimiter) {
        if(str == null) {
            return null;
        }
        str = str.replaceAll(" ", "");
        StringTokenizer strToken = new StringTokenizer(str, delimiter);
        String[] strArray = new String[strToken.countTokens()];
        int i = 0;

        while(strToken.hasMoreTokens()) {
            strArray[i++] = strToken.nextToken();
        }

        return strArray;
    }


    private String getString(String[] values) {
        if (values == null || values.length < 1 )
            return "";
        String str = values[0];
        for (int j = 1; j < values.length; j++) {
            str += ","+values[j];
        }

        return str;
    }


    public static final String  DISPLAY_NAMES	= "displayNames";
    public static final String  MODEL_NAMES	= "attributeNames";
    public static final String	OBJECT_NAME	= "objectName";
    public static final String	METHOD_NAME 	= "methodName";
    public static final String	POOL_NAME 	= "poolName";
    public static final String	MAP_NAME 	= "mapName";

    public static final String	GET_ATTRIBUTES_METHOD  = "getAttributes";
    public static final String	UPDATE_ATTRIBUTES_METHOD  = "updateSecurityMap";
    
    public static final String  MODEL_NAME	= "name";
    public static final String  MODEL_PRINCIPAL	= "principal";
    public static final String	MODEL_GROUP	= "user_group";
    public static final String	MODEL_USERNAME 	= "user_name";
    public static final String	MODEL_PASSWORD	= "password";
    public static final String  MODEL_POOLNAME	= "pool_name";
    public static final String	MODEL_ADD_PRINCIPALS = "add_principals";
    public static final String	MODEL_REMOVE_PRINCIPALS	= "remove_principals";
    public static final String	MODEL_ADD_GROUPS = "add_user_groups";
    public static final String	MODEL_REMOVE_GROUPS = "remove_user_groups";

    public static final String  DIPSLAY_NAME	= "name";
    public static final String  DISPLAY_PRINCIPAL = "principals";
    public static final String  DISPLAY_PRINCIPAL_ORIG = "principalsOrig";
    public static final String	DISPLAY_GROUP	= "userGroups";
    public static final String	DISPLAY_GROUP_ORIG = "userGroupsOrig";
    public static final String	DISPLAY_USERNAME = "username";
    public static final String	DISPLAY_PASSWORD = "password";


    public static final String	SESSION_GROUPS 	= "groups";
    public static final String	SESSION_PRINCIPALS = "principals";
}
