/*
 * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved.
 *
 * The contents of this file are subject to the CCM Public
 * License (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the
 * License at http://www.redhat.com/licenses/ccmpl.html.
 *
 * Software distributed under the License is distributed on an
 * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
 * or implied. See the License for the specific language
 * governing rights and limitations under the License.
 *
 */
package com.arsdigita.cms.ui.permissions;


import com.arsdigita.bebop.BoxPanel;
import com.arsdigita.bebop.Form;
import com.arsdigita.bebop.FormData;
import com.arsdigita.bebop.FormProcessException;
import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.SegmentedPanel;
import com.arsdigita.bebop.event.FormSectionEvent;
import com.arsdigita.bebop.event.FormSubmissionListener;
import com.arsdigita.bebop.event.PrintEvent;
import com.arsdigita.bebop.event.PrintListener;
import com.arsdigita.bebop.form.CheckboxGroup;
import com.arsdigita.bebop.form.Option;
import com.arsdigita.bebop.form.OptionGroup;
import com.arsdigita.bebop.form.Submit;
import com.arsdigita.bebop.parameters.ArrayParameter;
import com.arsdigita.bebop.parameters.StringParameter;
import com.arsdigita.cms.ContentItem;
import com.arsdigita.kernel.ACSObject;
import com.arsdigita.kernel.Party;
import com.arsdigita.kernel.PartyCollection;
import com.arsdigita.kernel.permissions.PermissionDescriptor;
import com.arsdigita.kernel.permissions.PermissionService;
import com.arsdigita.kernel.permissions.PrivilegeDescriptor;
import com.arsdigita.util.StringUtils;
import com.arsdigita.util.UncheckedWrapperException;

import java.math.BigDecimal;
import java.util.TooManyListenersException;


/**
 * Permissions Grant container for permissions assignment.
 * Widgets are currently organized on a bebop SegmentedPanel.
 *
 * @author Stefan Deusch (sdeusch@arsdigita.com)
 * @version $Id: //cms/dev/src/com/arsdigita/cms/ui/permissions/CMSPermissionsGrant.java#9 $
 */

class CMSPermissionsGrant implements CMSPermissionsConstants {

    private final static String PARTIES_CBG = "parties_cbg";
    private final static String PRIVILEGES_CBG  = "privs_cbg";

    // data keys
    private static final String USER_ID        = "userID";
    private static final String SCREEN_NAME    = "screenName";
    private static final String FIRST_NAME     = "firstName";
    private static final String LAST_NAME      = "lastName";

    private SegmentedPanel  m_grantPanel;
    private CMSPermissionsPane m_parent;
    private CheckboxGroup   m_parties;
    private CheckboxGroup   m_privileges;
    private Form            m_form;
    private Submit          m_save;



    /**
     * Creates a PermissionsGrant object that will be contained with
     * another component. This is currently used inside the
     * permissions pane.
     *
     * @param parent the enclosing container
     */

    public CMSPermissionsGrant(CMSPermissionsPane parent) {
        m_parent = parent;
        makeForm();
        m_grantPanel = new SegmentedPanel();
        m_grantPanel.addSegment(new Label(PAGE_GRANT_TITLE), m_form);
    }


    /**
     * Builds the form used to grant pivileges to users and groups.
     */

    private void makeForm() {
        m_form = new Form("GrantPrivileges", new BoxPanel());
        m_form.setMethod(Form.POST);
        m_form.addSubmissionListener(new GrantFormSubmissionListener());
        m_form.add(new Label(PAGE_GRANT_LEFT));
        m_parties = new CheckboxGroup(PARTIES_CBG);
        try {
            m_parties.addPrintListener(new UserSearchPrintListener());
        } catch (TooManyListenersException e) {
            throw new UncheckedWrapperException("TooManyListeners: " + e.getMessage(), e);
        }
        m_form.add(m_parties);

        m_form.add(new Label(PAGE_GRANT_RIGHT));
        m_privileges = new CheckboxGroup(PRIVILEGES_CBG);
        try {
            m_privileges.addPrintListener(new PrivilegePrintListener());
        } catch (TooManyListenersException e) {
            throw new UncheckedWrapperException("TooManyListeners: " + e.getMessage(), e);
        }
        m_form.add(m_privileges);

        m_save = new Submit("save", SAVE_BUTTON);
        m_form.add(m_save);
    }

    /**
     * Returns the SegmentedPanel with the permissions grant Form
     *
     * @return the SegmentedPanel with the permissions grant form
     */

    public SegmentedPanel getPanel() {
        return m_grantPanel;
    }

    private class GrantFormSubmissionListener
        implements FormSubmissionListener {
        public void submitted(FormSectionEvent e) throws FormProcessException {
            PageState state = e.getPageState();
            FormData data = e.getFormData();
            String[] gids = (String[])data.get(PARTIES_CBG);
            String[] privs = (String[])data.get(PRIVILEGES_CBG);
            if (privs != null && gids != null) {
                BigDecimal oID = m_parent.getObject(state).getID();
                BigDecimal gID = null;
                CMSUserObjectStruct uos = null;
                PermissionDescriptor pmd = null;
                for(int j=0; j<gids.length; j++) {
                    gID = new BigDecimal(gids[j]);
                    uos = new CMSUserObjectStruct(gID, oID);
                    for(int k=0; k<privs.length; k++) {
                        ACSObject acsObj = uos.getObject();
                        pmd = new
                            PermissionDescriptor(PrivilegeDescriptor.
                                                 get(privs[k]),
                                                 acsObj,
                                                 uos.getParty());
                        PermissionService.grantPermission(pmd);

                        if (acsObj instanceof ContentItem) {
                            ContentItem item = (ContentItem) acsObj;
                            ContentItem liveVersion = item.getLiveVersion();
                            if (liveVersion != null) {
                                pmd = new
                                    PermissionDescriptor(PrivilegeDescriptor.
                                                         get(privs[k]),
                                                         liveVersion,
                                                         uos.getParty());
                                PermissionService.grantPermission(pmd);
                            }
                        }
                    }
                }
            }
            m_parent.showAdmin(state);
        }
    }

    private class UserSearchPrintListener implements PrintListener {
        public void prepare(PrintEvent e) {
            PageState state = e.getPageState();
            OptionGroup cbg = (CheckboxGroup)e.getTarget();

            // get query string
            String search = (String)state.
                getValue(new StringParameter(SEARCH_QUERY));
            search = StringUtils.stripWhiteSpace(search);

            PartyCollection parties = Party.retrieveAllParties();
            parties.filter(search);

            String userID, userName;
            while(parties.next()) {
                userID = parties.getID().toString();
                userName = parties.getDisplayName();
                cbg.addOption(new Option(userID, userName));
            }
            parties.close();

            // DataQuery query = SessionManager.getSession().
            //     retrieveQuery(RETRIEVE_USERS);
            // query.setParameter("excludeGroupId", null);
            //
            // Filter f = query.addFilter
            //     ("searchName like lower('%' || :searchQuery || '%')");
            // f.set("searchQuery", search);
            //
            // String userID, userName;
            // while(query.next()) {
            //     userID = query.get(USER_ID).toString();
            //     userName = query.get(FIRST_NAME)+" "+query.get(LAST_NAME);
            //     cbg.addOption(new Option(userID, userName));
            // }
            // query.close();
        }
    }

    private class PrivilegePrintListener implements PrintListener {
        public void prepare(PrintEvent e) {
            PageState state = e.getPageState();
            OptionGroup cbg = (CheckboxGroup)e.getTarget();

            // get privileges from page state
            Object[] pa = (Object[])state.
                getValue(new ArrayParameter(PRIV_SET));

            // print ceckbox group with privileges
            for (int i=0; i<pa.length; i++) {
                cbg.addOption
                    (new Option((String)pa[i],
                                m_parent.getPrivilegeName((String)pa[i])));
            }
        }
    }
}
